文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

如何进行TCP通信实现

2023-06-05 04:09

关注

本篇文章给大家分享的是有关如何进行TCP通信实现,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

TCP是底层通讯协议,定义的是数据传输和连接方式的规范。TCP协议,传输控制协议(Transmission Control Protocol,缩写为:TCP)是一种面向连接的、可靠的、基于字节流的通信协议。讲到TCP协议就绕不开套接字Socket。这也是搞软件开发经常接触的技术点。 套接字Socket是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。 创建Socket连接时,可以指定使用的传输层协议,Socket可以支持不同的传输层协议(TCP或UDP),当使用TCP协议进行连接时,该Socket连接就是一个TCP连接。

在网络通讯中,从架构设计和应用需要具备抽象思维。让阅读者和使用者非常清晰的理解设计思路。采用割裂思维。形象的比喻成大炮和炮弹。大炮。发射装置分HTTP和TCP。收发机制不同。每种编程语言都有自己固定的API实现。炮弹就是二进制流数据。不固定完全可以DIY。就是我们常说的通信协议。所谓“协议”是双方共同遵守的规则。协议有语法、语义、时序三要素。炮弹抽象转实体就是Gk8ByteMaker。具体实现参阅。网络通信1:字节流的封装。针对大炮发射装置实现。其实许多编程语言都不需要自己造轮子。甚至很多框架支持、比如Java有名气的MINA框架。作为编程者应该需要探索的欲望。自己实现过对底层的理解更透彻。领悟过记忆才更深刻。曾经有个面试者就理直气壮说Socket底层就是可以直接传输类对象。因为他工作接触的都是完善的框架。直接面向对象编程。缺乏捅破窗户纸窥探下底层真正的实现原理。

项目使用C++实现网络TCP通信(tcpnet)。其中Gk8Socket是实现底层Socket通信。Gk8TcpService是提供接口服务。方便使用者方便快捷的使用。同时发射装置肯定需要炮弹。也使用了Gk8ByteMaker。每种编程语言实现都有差异。这里仅抛砖引玉。重点还是理解思维和原理。记忆容易忘记。思维不容易忘记。

C++实现网络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;    //[定义一些创建标记宏]    #define INVALID_SOCKET    -1    #define SOCKET_ERROR    -1#endifclass Gk8Socket{protected://[类保护属性]    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++实现网络Socket类:Gk8Socket.cpp

#include "Gk8Socket.h"#include "Gk8OperSys.h"#include <stdio.h>#if(GK8_TARGET_PLATFORM==GK8_PLATFORM_WIN32)#pragma comment(lib, "wsock32")#endifGk8Socket::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;}//[创建套接字]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;}//[服务器监听端口]bool Gk8Socket::Listen(int backlog){    int ret = listen(m_iSocket, backlog);    if (ret == SOCKET_ERROR)    {        return false;    }    return true;}//[服务器接受套接字]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);    //[第一个参数是0和sockfd中的最大值加一]    //[第二个参数是读集,也就是sockset]    //[第三,四个参数是写集和异常集,在本程序中都为空]    //[第五个参数是超时时间,即在指定时间内仍没有可读,则出错]    if(result==-1)    {        return -1;    }else    {        if(FD_ISSET(m_iSocket,&m_fdR)>0)        {            return -2;        }else        {            return -3;        }    }}//[发送数据:直接发送]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;}//[接受数据]int Gk8Socket::Recv(char* buf, int len, int flags){    return (GK8_INT)recv(m_iSocket,buf,len,flags);}//[关闭SOCKET]int Gk8Socket::Close(){#if(GK8_TARGET_PLATFORM==GK8_PLATFORM_WIN32)    return (closesocket(m_iSocket));#else    return (close(m_iSocket));#endif}//[获取错误信息]int Gk8Socket::GetError(){#if(GK8_TARGET_PLATFORM==GK8_PLATFORM_WIN32)    return (WSAGetLastError());#else    return -1;#endif}

C++实现Tcp服务类: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>#endifclass Gk8TcpService:public Gk8BaseObj{    DECLARE_TOSPP_MAP;private:    pthread_t m_nPId;                    //[线程ID]    GK8_BOOL m_bCreatePthread;            //[创建了线程]    Gk8ByteMaker m_iRequestData;        //[TCP请求数据]public:    Gk8Socket m_iSocket;    Gk8Str m_iHostIpStr;                //[服务器IP]    GK8_INT m_nPort;                    //[服务端口]    pthread_mutex_t mt_TcpResponseMutex;//[TCP响应互斥体]    Gk8ByteMaker m_iTcpData;            //[TCP反馈数据]private:    static void* start_thread(void*);    //[静态成员函数,相当于C中的全局函数]    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();            //[函数中止当前线程]    static GK8_VOID TcpClientTick();};#endif

C++实现Tcp服务类:Gk8TcpService.cpp

#include "Gk8TcpService.h"//[TCP SOCKET错误编码]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");        //[接收网络信息]static Gk8SortMap sg_iTcpSocketMap;                                //[委托MAP]//[用来管理回调的]/////////////////////////////////////////////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);}//[套接字失败回调]GK8_VOID Gk8TcpService::TcpSocketFailCallBack(GK8_INT nFailCode){    OnCall(sg_iTcpSocketFailEventFun,Gk8Var()<<nFailCode);}//[套接字成功回调]GK8_VOID Gk8TcpService::TcpSocketSuccCallBack(){    OnCall(sg_iTcpSocketSuccEventFun);}//[创建套接字并连接.启动套接字线程]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;        //[但是上面这个函数其他内容则主要为你创建的线程设定为分离式]        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;    }    //[创建套接字]    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();    //[循环监听.接收数据]    Gk8ByteMaker sl_iRecvBuf;    sl_iRecvBuf.WriteAlloc(1024*1024);    GK8_INT nRecvLen=0;    while(true)    {        //[表示服务器端有消息推送过来.会接受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;}//[发送消息]GK8_VOID Gk8TcpService::SendMessage(Gk8ByteMaker* pRequestData){    pRequestData->ShiftTo(m_iRequestData);    TcpRequestStarted();}//[把二进制流重组成新的对象]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();}//[向脚本派发消息]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);    //[把数据往前提]    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();    }}

以上就是如何进行TCP通信实现,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯