Socket 封包与拆包入门程序示例

      最近自己做了一个简单的MFC Socket开发的项目,由于第一次接触,所以费了一些力气,现把比较好的经验整理如下,希望对刚开始做相关开发工作的人员能有所帮助,有问题处还希望能留言指出。


Socket开发应解决的两个基本问题:

        1)Client 与 Server的连接通讯,可参考

MFC/Socket网络编程:[1]服务器”, 链接:https://jingyan.baidu.com/article/676629974557c254d51b84da.html

                 MFC/Socket网络编程:[1]客户端”, 链接:https://jingyan.baidu.com/article/ed15cb1b7601021be36981db.html

             上面两篇文档很好,做上两遍例子,仔细理逻辑,就能很快编写自己的C/S(照着写可能会报错,百度错误号,很好解决)。


        2)数据的封包与拆包,下面将部分关键代码摘出,自己仔细把逻辑理通,相信很快能写自己的封包与拆包程序。


封包代码:

bool TCPServer::SendData( unsigned short nOpcode, const char* pDataBuffer, const unsigned int& nDataSize )
{
NetPacketHeader* pHead = (NetPacketHeader*) m_cbSendBuf; //将发送缓存区的字符指针,转换成一个包头的结构体指针


pHead->wOpcode = nOpcode; //将操作命令保存到发送缓存区

// 数据封包
if ( (nDataSize > 0) && (pDataBuffer != 0) )
{
CopyMemory(pHead+1, pDataBuffer, nDataSize); //将数据信息保存到缓存区(在包头后)
}


// 发送消息
const unsigned short nSendSize = nDataSize + sizeof(NetPacketHeader);
pHead->wDataSize = nSendSize;
int ret = ::send(mAcceptSocket, m_cbSendBuf, nSendSize, 0);
return (ret > 0) ? true : false;
}


拆包代码:

void TCPClient::run()
{
int nCount = 0;
for (;;) //开启循环,直到将所有的数据接收完break退出
{
// 接收数据
int nRecvSize = ::recv(mServerSocket,
m_cbRecvBuf+m_nRecvSize, 
sizeof(m_cbRecvBuf)-m_nRecvSize, 0); //仔细读这句话,每次收到的数据都保存在缓存区的新位置(紧接着已经接收到的字节),不是覆盖
if (nRecvSize <= 0)
{
std::cout << "服务器主动断开连接!" << std::endl;
break;
}


// 保存已经接收数据的大小
m_nRecvSize += nRecvSize; //m_nRecvSize 在run之前已经初始化为0,这只是部分代码,重点看逻辑


// 接收到的数据够不够一个包头的长度
while (m_nRecvSize >= sizeof(NetPacketHeader))
{
// 收够10个包,主动与服务器断开
if (nCount >= 10)
{
::closesocket(mServerSocket);
break;
}


// 读取包头
NetPacketHeader* pHead = (NetPacketHeader*) (m_cbRecvBuf); //此处解读包头与写入包头的方式一致
const unsigned short nPacketSize = pHead->wDataSize;


// 判断是否已接收到足够一个完整包的数据
if (m_nRecvSize < nPacketSize)
{
// 还不够拼凑出一个完整包
break;
}


// 拷贝到数据缓存
CopyMemory(m_cbDataBuf, m_cbRecvBuf, nPacketSize);


// 从接收缓存移除
MoveMemory(m_cbRecvBuf, m_cbRecvBuf+nPacketSize, m_nRecvSize);
m_nRecvSize -= nPacketSize;


// 解密数据,以下省略一万字
// ...


// 分派数据包,让应用层进行逻辑处理
pHead = (NetPacketHeader*) (m_cbDataBuf);
const unsigned short nDataSize = nPacketSize - (unsigned short)sizeof(NetPacketHeader);
OnNetMessage(pHead->wOpcode, m_cbDataBuf+sizeof(NetPacketHeader), nDataSize);


++nCount;
}
}


std::cout << "已经和服务器断开连接!" << std::endl;
}

上面只是摘出了部分代码,可仔细阅读整个工程,很适合入门,建议仔细阅读。源代码链接如下:https://download.csdn.net/download/wqvbjhc/3989216#comment


版权声明:本文为博主原创文章,转载请注明出处。


  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值