本篇文章給大家分享的是有關(guān)如何進(jìn)行TCP通信實(shí)現(xiàn),小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
10年積累的成都網(wǎng)站設(shè)計(jì)、網(wǎng)站制作經(jīng)驗(yàn),可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識你,你也不認(rèn)識我。但先做網(wǎng)站設(shè)計(jì)后付款的網(wǎng)站建設(shè)流程,更有孝義免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。TCP是底層通訊協(xié)議,定義的是數(shù)據(jù)傳輸和連接方式的規(guī)范。TCP協(xié)議,傳輸控制協(xié)議(Transmission Control Protocol,縮寫為:TCP)是一種面向連接的、可靠的、基于字節(jié)流的通信協(xié)議。講到TCP協(xié)議就繞不開套接字Socket。這也是搞軟件開發(fā)經(jīng)常接觸的技術(shù)點(diǎn)。 套接字Socket是通信的基石,是支持TCP/IP協(xié)議的網(wǎng)絡(luò)通信的基本操作單元。它是網(wǎng)絡(luò)通信過程中端點(diǎn)的抽象表示,包含進(jìn)行網(wǎng)絡(luò)通信必須的五種信息:連接使用的協(xié)議,本地主機(jī)的IP地址,本地進(jìn)程的協(xié)議端口,遠(yuǎn)地主機(jī)的IP地址,遠(yuǎn)地進(jìn)程的協(xié)議端口。 創(chuàng)建Socket連接時(shí),可以指定使用的傳輸層協(xié)議,Socket可以支持不同的傳輸層協(xié)議(TCP或UDP),當(dāng)使用TCP協(xié)議進(jìn)行連接時(shí),該Socket連接就是一個(gè)TCP連接。
在網(wǎng)絡(luò)通訊中,從架構(gòu)設(shè)計(jì)和應(yīng)用需要具備抽象思維。讓閱讀者和使用者非常清晰的理解設(shè)計(jì)思路。采用割裂思維。形象的比喻成大炮和炮彈。大炮。發(fā)射裝置分HTTP和TCP。收發(fā)機(jī)制不同。每種編程語言都有自己固定的API實(shí)現(xiàn)。炮彈就是二進(jìn)制流數(shù)據(jù)。不固定完全可以DIY。就是我們常說的通信協(xié)議。所謂“協(xié)議”是雙方共同遵守的規(guī)則。協(xié)議有語法、語義、時(shí)序三要素。炮彈抽象轉(zhuǎn)實(shí)體就是Gk8ByteMaker。具體實(shí)現(xiàn)參閱。 網(wǎng)絡(luò)通信1:字節(jié)流的封裝。針對大炮發(fā)射裝置實(shí)現(xiàn)。其實(shí)許多編程語言都不需要自己造輪子。甚至很多框架支持、比如Java有名氣的MINA框架。作為編程者應(yīng)該需要探索的欲望。自己實(shí)現(xiàn)過對底層的理解更透徹。領(lǐng)悟過記憶才更深刻。曾經(jīng)有個(gè)面試者就理直氣壯說Socket底層就是可以直接傳輸類對象。因?yàn)樗ぷ鹘佑|的都是完善的框架。直接面向?qū)ο缶幊?。缺乏捅破窗戶紙窺探下底層真正的實(shí)現(xiàn)原理。
項(xiàng)目使用C++實(shí)現(xiàn)網(wǎng)絡(luò)TCP通信(tcpnet)。其中Gk8Socket是實(shí)現(xiàn)底層Socket通信。Gk8TcpService是提供接口服務(wù)。方便使用者方便快捷的使用。同時(shí)發(fā)射裝置肯定需要炮彈。也使用了Gk8ByteMaker。每種編程語言實(shí)現(xiàn)都有差異。這里僅拋磚引玉。重點(diǎn)還是理解思維和原理。記憶容易忘記。思維不容易忘記。
C++實(shí)現(xiàn)網(wǎng)絡(luò)Socket類:Gk8Socket.h
#ifndef _GK8SOCKET_H_ #define _GK8SOCKET_H_ #pragma once #include "Gk8Env.h" #if(GK8_TARGET_PLATFORM==GK8_PLATFORM_WIN32) #include <winsock2.h> typedef int socklen_t; #else #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <fcntl.h> #include <unistd.h> #include <sys/stat.h> #include <sys/types.h> #include <arpa/inet.h> typedef int SOCKET; //[定義一些創(chuàng)建標(biāo)記宏] #define INVALID_SOCKET -1 #define SOCKET_ERROR -1 #endif class Gk8Socket { protected://[類保護(hù)屬性] SOCKET m_iSocket; //[SCOKET套接字] fd_set m_fdR; //[SCOKET信息] public://[類公共屬性] Gk8Socket(SOCKET iSocket=INVALID_SOCKET); ~Gk8Socket(); static int Init(); static int Clean(); Gk8Socket& operator=(SOCKET iSocket); operator SOCKET(); bool Create(int af, int type, int protocol = 0); bool Connect(const char* ip, unsigned short port); bool Bind(unsigned short port); bool Listen(int backlog = 5); bool Accept(Gk8Socket& s, char* fromip = NULL); int Select(); int Send(const char* buf, int len, int flags=0); int Recv(char* buf, int len, int flags=0); int Close(); int GetError(); }; #endif
C++實(shí)現(xiàn)網(wǎng)絡(luò)Socket類:Gk8Socket.cpp
#include "Gk8Socket.h" #include "Gk8OperSys.h" #include <stdio.h> #if(GK8_TARGET_PLATFORM==GK8_PLATFORM_WIN32) #pragma comment(lib, "wsock32") #endif Gk8Socket::Gk8Socket(SOCKET iSocket) { m_iSocket=iSocket; } Gk8Socket::~Gk8Socket() { } //[初始化SOCKET] int Gk8Socket::Init() { #if(GK8_TARGET_PLATFORM==GK8_PLATFORM_WIN32) WSADATA wsaData; WORD version = MAKEWORD(2, 0); int nRet = WSAStartup(version, &wsaData);//[WinSock啟動] if(nRet) { _GK8ERR<<"Initilize winsock error !"<<CR; return -1; } #endif return 0; } //[清理SOCKET] int Gk8Socket::Clean() { #if(GK8_TARGET_PLATFORM==GK8_PLATFORM_WIN32) return (WSACleanup()); #endif return 0; } Gk8Socket& Gk8Socket::operator=(SOCKET iSocket) { m_iSocket=iSocket; return (*this); } Gk8Socket::operator SOCKET() { return m_iSocket; } //[創(chuàng)建套接字] bool Gk8Socket::Create(int af, int type,int protocol) { m_iSocket=socket(af, type, protocol); if(m_iSocket==INVALID_SOCKET) { return false; } return true; } //[連接SOCKET] bool Gk8Socket::Connect(const char* ip,unsigned short port) { struct sockaddr_in svraddr; svraddr.sin_family = AF_INET; svraddr.sin_addr.s_addr = inet_addr(ip); svraddr.sin_port = htons(port); int ret=connect(m_iSocket,(struct sockaddr*)&svraddr,sizeof(svraddr)); if (ret==SOCKET_ERROR) { return false; } return true; } //[綁定端口] bool Gk8Socket::Bind(unsigned short port) { struct sockaddr_in svraddr; svraddr.sin_family = AF_INET; svraddr.sin_addr.s_addr = INADDR_ANY; svraddr.sin_port = htons(port); int opt = 1; if (setsockopt(m_iSocket, SOL_SOCKET, SO_REUSEADDR, (char*) &opt, sizeof(opt))< 0) return false; int ret = bind(m_iSocket,(struct sockaddr*)&svraddr,sizeof(svraddr)); if (ret==SOCKET_ERROR) { return false; } return true; } //[服務(wù)器監(jiān)聽端口] bool Gk8Socket::Listen(int backlog) { int ret = listen(m_iSocket, backlog); if (ret == SOCKET_ERROR) { return false; } return true; } //[服務(wù)器接受套接字] bool Gk8Socket::Accept(Gk8Socket& s,char* fromip) { struct sockaddr_in cliaddr; socklen_t addrlen = sizeof(cliaddr); SOCKET sock = accept(m_iSocket,(struct sockaddr*)&cliaddr,&addrlen); if(sock == SOCKET_ERROR) { return false; } s=sock; if (fromip != NULL) sprintf(fromip, "%s", inet_ntoa(cliaddr.sin_addr)); return true; } int Gk8Socket::Select() { FD_ZERO(&m_fdR); FD_SET(m_iSocket,&m_fdR); struct timeval mytimeout; mytimeout.tv_sec=3; mytimeout.tv_usec=0; int result=select(m_iSocket+1,&m_fdR,NULL,NULL,NULL); //[第一個(gè)參數(shù)是0和sockfd中的大值加一] //[第二個(gè)參數(shù)是讀集,也就是sockset] //[第三,四個(gè)參數(shù)是寫集和異常集,在本程序中都為空] //[第五個(gè)參數(shù)是超時(shí)時(shí)間,即在指定時(shí)間內(nèi)仍沒有可讀,則出錯(cuò)] if(result==-1) { return -1; }else { if(FD_ISSET(m_iSocket,&m_fdR)>0) { return -2; }else { return -3; } } } //[發(fā)送數(shù)據(jù):直接發(fā)送] int Gk8Socket::Send(const char* buf, int len, int flags) { int bytes; int count = 0; while(count<len) { bytes=(GK8_INT)send(m_iSocket,buf+count,len-count,flags); if(bytes==-1||bytes==0) return -1; count+=bytes; } return count; } //[接受數(shù)據(jù)] int Gk8Socket::Recv(char* buf, int len, int flags) { return (GK8_INT)recv(m_iSocket,buf,len,flags); } //[關(guān)閉SOCKET] int Gk8Socket::Close() { #if(GK8_TARGET_PLATFORM==GK8_PLATFORM_WIN32) return (closesocket(m_iSocket)); #else return (close(m_iSocket)); #endif } //[獲取錯(cuò)誤信息] int Gk8Socket::GetError() { #if(GK8_TARGET_PLATFORM==GK8_PLATFORM_WIN32) return (WSAGetLastError()); #else return -1; #endif }
C++實(shí)現(xiàn)Tcp服務(wù)類:Gk8TcpService.h
#ifndef __GK8TCPSERVICE_H__ #define __GK8TCPSERVICE_H__ #pragma once #include "Gk8Socket.h" #include "Gk8BaseObj.h" #include "Gk8ByteMaker.h" #include <pthread.h> #include <semaphore.h> #if(GK8_TARGET_PLATFORM==GK8_PLATFORM_IOS||GK8_TARGET_PLATFORM==GK8_PLATFORM_ANDROID) #include <sys/time.h> #endif class Gk8TcpService:public Gk8BaseObj { DECLARE_TOSPP_MAP; private: pthread_t m_nPId; //[線程ID] GK8_BOOL m_bCreatePthread; //[創(chuàng)建了線程] Gk8ByteMaker m_iRequestData; //[TCP請求數(shù)據(jù)] public: Gk8Socket m_iSocket; Gk8Str m_iHostIpStr; //[服務(wù)器IP] GK8_INT m_nPort; //[服務(wù)端口] pthread_mutex_t mt_TcpResponseMutex;//[TCP響應(yīng)互斥體] Gk8ByteMaker m_iTcpData; //[TCP反饋數(shù)據(jù)] private: static void* start_thread(void*); //[靜態(tài)成員函數(shù),相當(dāng)于C中的全局函數(shù)] GK8_VOID TcpSocketFailCallBack(GK8_INT nFailCode); GK8_VOID TcpSocketSuccCallBack(); GK8_VOID TcpRequestStarted(); GK8_VOID DispatcherReceiveMessage(); public: Gk8TcpService(); ~Gk8TcpService(); GK8_BOOL TOSPPFUNC Build(GK8_LPCSTR lpHostIp,GK8_INT nPort); GK8_VOID TOSPPFUNC SendMessage(Gk8ByteMaker* pRequestData); GK8_VOID TOSPPFUNC PutMessage(Gk8ByteMaker* pRequestData); GK8_VOID TOSPPFUNC SendCachedMessage(); GK8_VOID TOSPPFUNC Close(); //[函數(shù)中止當(dāng)前線程] static GK8_VOID TcpClientTick(); }; #endif
C++實(shí)現(xiàn)Tcp服務(wù)類:Gk8TcpService.cpp
#include "Gk8TcpService.h" //[TCP SOCKET錯(cuò)誤編碼] enum TCPSOCKETFAILERRORCODE { TCPCODE_PTHREAD_FAIL=0, TCPCODE_SOCKET_INIT_FAIL, TCPCODE_SOCKET_CREATE_FAIL, TCPCODE_SOCKET_CONNECT_FAIL, TCPCODE_SOCKET_SEND_FAIL, TCPCODE_END }; static Gk8Var sg_iTcpSocketFailEventFun("OnTcpSocketFail"); //[TCPSOCKET失敗信息] static Gk8Var sg_iTcpSocketSuccEventFun("OnTcpSocketSucc"); //[TCPSOCKET成功信息] static Gk8Var sg_iTcpReceiveMessageFun("ReceiveMessage"); //[接收網(wǎng)絡(luò)信息] static Gk8SortMap sg_iTcpSocketMap; //[委托MAP]//[用來管理回調(diào)的] /////////////////////////////////////////////CLASS-TOSPP//////////////////////////////////////////////////// BEGIN_TOSPP_MAP(Gk8TcpService,Gk8BaseObj) TOSPP_FUNC(Gk8TcpService,Build,'b',"sd","Build(lpHostIp,nPort)") TOSPP_FUNC(Gk8TcpService,SendMessage,' ',"p","SendMessage(iRequestDataPtr)") TOSPP_FUNC(Gk8TcpService,PutMessage,' ',"p","PutMessage(iRequestDataPtr)") TOSPP_FUNC(Gk8TcpService,SendCachedMessage,' '," ","SendCachedMessage()") TOSPP_FUNC(Gk8TcpService,Close,' ',"","Close()") END_TOSPP_MAP() /////////////////////////////////////[套接字邏輯]/////////////////////////////////////////////// Gk8TcpService::Gk8TcpService() { pthread_mutex_init(&mt_TcpResponseMutex,NULL); sg_iTcpSocketMap.AddItem((GK8_PTR_TYPE)this,0); m_bCreatePthread=false; } Gk8TcpService::~Gk8TcpService() { pthread_mutex_destroy(&mt_TcpResponseMutex); sg_iTcpSocketMap.RemoveItem((GK8_PTR_TYPE)this); } //[套接字失敗回調(diào)] GK8_VOID Gk8TcpService::TcpSocketFailCallBack(GK8_INT nFailCode) { OnCall(sg_iTcpSocketFailEventFun,Gk8Var()<<nFailCode); } //[套接字成功回調(diào)] GK8_VOID Gk8TcpService::TcpSocketSuccCallBack() { OnCall(sg_iTcpSocketSuccEventFun); } //[創(chuàng)建套接字并連接.啟動套接字線程] GK8_BOOL Gk8TcpService::Build(GK8_LPCSTR lpHostIp,GK8_INT nPort) { m_iRequestData.Destroy(); m_iTcpData.Destroy(); m_iHostIpStr=lpHostIp; m_nPort=nPort; int errCode=0; do { pthread_attr_t tAttr; errCode=pthread_attr_init(&tAttr); if(errCode!=0) return false; //[但是上面這個(gè)函數(shù)其他內(nèi)容則主要為你創(chuàng)建的線程設(shè)定為分離式] errCode=pthread_attr_setdetachstate(&tAttr,PTHREAD_CREATE_DETACHED); if(errCode!=0) { pthread_attr_destroy(&tAttr); TcpSocketFailCallBack(TCPCODE_PTHREAD_FAIL); return false; } m_bCreatePthread=true; errCode=pthread_create(&m_nPId,&tAttr,start_thread,this); if(errCode!=0) { pthread_attr_destroy(&tAttr); TcpSocketFailCallBack(TCPCODE_PTHREAD_FAIL); return false; } }while(0); return true; } //[套接字線程對象] void* Gk8TcpService::start_thread(void* arg) { Gk8TcpService* pTcpService=(Gk8TcpService*)arg; //[0表示連接成功.1表示連接失敗] Gk8Socket iSocket; if(iSocket.Init()!=0) { pTcpService->TcpSocketFailCallBack(TCPCODE_SOCKET_INIT_FAIL); return NULL; } //[創(chuàng)建套接字] if(!iSocket.Create(AF_INET,SOCK_STREAM,0)) { pTcpService->TcpSocketFailCallBack(TCPCODE_SOCKET_CREATE_FAIL); return NULL; } //[連接套接字] if(!iSocket.Connect(pTcpService->m_iHostIpStr,pTcpService->m_nPort)) { pTcpService->TcpSocketFailCallBack(TCPCODE_SOCKET_CONNECT_FAIL); return NULL; } pTcpService->m_iSocket=iSocket; //[通知連接成功] pTcpService->TcpSocketSuccCallBack(); //[循環(huán)監(jiān)聽.接收數(shù)據(jù)] Gk8ByteMaker sl_iRecvBuf; sl_iRecvBuf.WriteAlloc(1024*1024); GK8_INT nRecvLen=0; while(true) { //[表示服務(wù)器端有消息推送過來.會接受HTTP的請求返回] if(iSocket.Select()==-2) { sl_iRecvBuf.ClearStream(); nRecvLen=iSocket.Recv((GK8_LPSTR)sl_iRecvBuf.GetBuf(),1024*1024,0); if(nRecvLen<=0) continue; //[多線程控制] pthread_mutex_lock(&pTcpService->mt_TcpResponseMutex); pTcpService->m_iTcpData.WriteBuf(sl_iRecvBuf.GetBuf(),nRecvLen); pthread_mutex_unlock(&pTcpService->mt_TcpResponseMutex); } } return NULL; } //[發(fā)送消息] GK8_VOID Gk8TcpService::SendMessage(Gk8ByteMaker* pRequestData) { pRequestData->ShiftTo(m_iRequestData); TcpRequestStarted(); } //[把二進(jìn)制流重組成新的對象] GK8_VOID Gk8TcpService::PutMessage(Gk8ByteMaker* pRequestData) { pRequestData->ShiftTo(m_iRequestData); } GK8_VOID Gk8TcpService::SendCachedMessage() { TcpRequestStarted(); } //[開始TCP請求] GK8_VOID Gk8TcpService::TcpRequestStarted() { GK8_INT nSendLen=m_iRequestData.GetStreamSize(); if(m_iSocket.Send((GK8_LPCSTR)m_iRequestData.GetBuf(),nSendLen)!=nSendLen) { TcpSocketFailCallBack(TCPCODE_SOCKET_SEND_FAIL); return ; } m_iRequestData.ClearStream(); } //[向腳本派發(fā)消息] GK8_VOID Gk8TcpService::DispatcherReceiveMessage() { if(m_iTcpData.GetStreamSize()<2*sizeof(GK8_WORD)) return; pthread_mutex_lock(&mt_TcpResponseMutex); Gk8Var iByteMakerVar(&m_iTcpData,m_iTcpData.GetObjId()); OnCall(sg_iTcpReceiveMessageFun,iByteMakerVar); //[把數(shù)據(jù)往前提] m_iTcpData.Pack(); pthread_mutex_unlock(&mt_TcpResponseMutex); } //[停止SOCKET] GK8_VOID Gk8TcpService::Close() { m_iSocket.Close(); #if(GK8_TARGET_PLATFORM==GK8_PLATFORM_ANDROID) _GK8ERR<<"Close"<<CR; pthread_detach(m_nPId); #endif #if(GK8_TARGET_PLATFORM==GK8_PLATFORM_IOS) pthread_cancel(m_nPId); pthread_detach(m_nPId); #endif #if(GK8_TARGET_PLATFORM==GK8_PLATFORM_WIN32) if(m_bCreatePthread) { m_bCreatePthread=false; pthread_cancel(m_nPId); pthread_detach(m_nPId); pthread_join(m_nPId,NULL); } #endif pthread_mutex_lock(&mt_TcpResponseMutex); m_iRequestData.Destroy(); m_iTcpData.Destroy(); pthread_mutex_unlock(&mt_TcpResponseMutex); } //[TCP客戶端檢測] GK8_VOID Gk8TcpService::TcpClientTick() { Gk8TcpService* pTcpService=NULL; for(GK8_INT i=0;i<sg_iTcpSocketMap.GetSize();i++) { pTcpService=(Gk8TcpService*)sg_iTcpSocketMap.GetItemIdAt(i); pTcpService->DispatcherReceiveMessage(); } }
以上就是如何進(jìn)行TCP通信實(shí)現(xiàn),小編相信有部分知識點(diǎn)可能是我們?nèi)粘9ぷ鲿姷交蛴玫降?。希望你能通過這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注創(chuàng)新互聯(lián)-成都網(wǎng)站建設(shè)公司行業(yè)資訊頻道。
網(wǎng)站名稱:如何進(jìn)行TCP通信實(shí)現(xiàn)-創(chuàng)新互聯(lián)
URL標(biāo)題:http://www.rwnh.cn/article44/dgsohe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)建站、面包屑導(dǎo)航、網(wǎng)站建設(shè)、App開發(fā)、虛擬主機(jī)、定制網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)