新聞中心
本篇文章給大家分享的是有關(guān)如何進(jìn)行TCP通信實(shí)現(xiàn),小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說(shuō),跟著小編一起來(lái)看看吧。
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ò)通信過(guò)程中端點(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ī)制不同。每種編程語(yǔ)言都有自己固定的API實(shí)現(xiàn)。炮彈就是二進(jìn)制流數(shù)據(jù)。不固定完全可以DIY。就是我們常說(shuō)的通信協(xié)議。所謂“協(xié)議”是雙方共同遵守的規(guī)則。協(xié)議有語(yǔ)法、語(yǔ)義、時(shí)序三要素。炮彈抽象轉(zhuǎn)實(shí)體就是Gk8ByteMaker。具體實(shí)現(xiàn)參閱。 網(wǎng)絡(luò)通信1:字節(jié)流的封裝。針對(duì)大炮發(fā)射裝置實(shí)現(xiàn)。其實(shí)許多編程語(yǔ)言都不需要自己造輪子。甚至很多框架支持、比如Java有名氣的MINA框架。作為編程者應(yīng)該需要探索的欲望。自己實(shí)現(xiàn)過(guò)對(duì)底層的理解更透徹。領(lǐng)悟過(guò)記憶才更深刻。曾經(jīng)有個(gè)面試者就理直氣壯說(shuō)Socket底層就是可以直接傳輸類對(duì)象。因?yàn)樗ぷ鹘佑|的都是完善的框架。直接面向?qū)ο缶幊獭H狈ν逼拼皯艏埜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。每種編程語(yǔ)言實(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) #includetypedef int socklen_t; #else #include #include #include #include #include #include #include #include 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#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啟動(dòng)] if(nRet) { _GK8ERR<<"Initilize winsock error !"< 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 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#include #if(GK8_TARGET_PLATFORM==GK8_PLATFORM_IOS||GK8_TARGET_PLATFORM==GK8_PLATFORM_ANDROID) #include #endif class Gk8TcpService:public Gk8BaseObj { DECLARE_TOSPP_MAP; private: pthread_t m_nPId; //[線程ID] GK8_BOOL m_bCreatePthread; //[創(chuàng)建了線程] Gk8ByteMaker m_iRequestData; //[TCP請(qǐng)求數(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]//[用來(lái)管理回調(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()<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ù)器端有消息推送過(guò)來(lái).會(huì)接受HTTP的請(qǐng)求返回] 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)制流重組成新的對(duì)象] GK8_VOID Gk8TcpService::PutMessage(Gk8ByteMaker* pRequestData) { pRequestData->ShiftTo(m_iRequestData); } GK8_VOID Gk8TcpService::SendCachedMessage() { TcpRequestStarted(); } //[開始TCP請(qǐng)求] 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"< DispatcherReceiveMessage(); } } 以上就是如何進(jìn)行TCP通信實(shí)現(xiàn),小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見到或用到的。希望你能通過(guò)這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注創(chuàng)新互聯(lián)-成都網(wǎng)站建設(shè)公司行業(yè)資訊頻道。
網(wǎng)頁(yè)標(biāo)題:如何進(jìn)行TCP通信實(shí)現(xiàn)-創(chuàng)新互聯(lián)
分享URL:http://www.ef60e0e.cn/article/dgsohe.html