在自己的WSASOCKET服务端/客户端中做了一个简单的解包程序处理粘包的问题

在自己的WSASOCKET服务端/客户端中做了一个简单的解包程序处理粘包的问题,各位达人能不能指点下这样的代码能不能应付一般的情况?

定义部分
C/C++ code
?
1
2
3
4
5
6
7
#define MYWSA_PACKSIZE 8192 //网络数据包完整字节数
#define MYWSA_HEADSIZE sizeof(int) * 2 //包头字节数
#define MYWSA_BUFSIZE MYWSA_PACKSIZE - MYWSA_HEADSIZE //网络数据包缓冲区字节数
 
#define MYWSA_SACCEPT 12013 //(LPARAM消息)服务端接收到客户端的连接
#define MYWSA_SLOST 12014 //(LPARAM消息)服务端失去与客户端的连接
#define MYWSA_SRECEIVE 12015 //(LPARAM消息)服务端接收到客户端的数据


结构部分
C/C++ code
?
1
2
3
4
5
6
struct  myWSAPack  //标准数据包结构
{
     int  WSALen;  //数据包长度
     int  WSAId;  //数据包ID
     char  Buffer[MYWSA_BUFSIZE];  //数据包内容
};


接收代码
C/C++ code
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
LRESULT  myWSAServer::OnReceive( WPARAM  wParam,  LPARAM  lParam)
{
     switch  (WSAGETSELECTEVENT(lParam))
     {
     case  FD_READ:
         {
             memset (m_Buffer, 0,  sizeof (m_Buffer));
             //TCP是流数据,发送方在连续发送时有可能集在一起发(粘包)
             int  Lenth = ::recv((SOCKET)wParam, m_Buffer,  sizeof (m_Buffer), 0);
 
             UnPack((SOCKET)wParam, m_Buffer, Lenth);
         }
         break ;
     case  FD_CLOSE:
         {
             myWSAEmpty data = {0};
 
             bool  Found =  false ;
             for  (myCliIt it = m_ClientQueue.begin(); it != m_ClientQueue.end(); ++ it)
             {
                 if  ((*it).sClient == (SOCKET)wParam)
                 {
                     Found =  true ;
                     closesocket((*it).sClient);  //销毁该SOCKET号的资源
 
                     sprintf_s(data.Addr,  sizeof (data.Addr),  "%s" , (*it).Addr);
                     m_ClientQueue.erase(it);
                     break ;
                 }
             }
 
             if  ( true  == Found)
             {
                 m_ClosedQue.push(data);
                 //投递消息,通知外部程序该客户端已关闭
                 ::PostMessage(m_MainHandle, m_MSGID, m_WPID, MYWSA_SLOST);
             }
         }
         break ;
     }
 
     return  1;
}


解包代码
C/C++ code
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
int  myWSAServer::UnPack(SOCKET sClient,  char  *Buffer,  int  Lenth)
{
     if  (Lenth <= 0 || NULL == Buffer)
     {
         return  -1;
     }
 
     int  Len = Lenth;
     char  *lpHead = Buffer;
     myWSAPack *lpPack = (myWSAPack*)lpHead;
 
     while  (Len > 0)
     {
         if  (lpPack->WSALen <= 0 || lpPack->WSALen > MYWSA_PACKSIZE)
         {
             sprintf_s(m_Log,  sizeof (m_Log),  "拆包出错:WSALen=%d" , lpPack->WSALen);
             Log(m_Log);
             return  -1;
         }
 
         if  (Len < lpPack->WSALen)
         {
             sprintf_s(m_Log,  sizeof (m_Log),  "拆包出错:len=%d != lPHead->WSALen=%d" , Len, lpPack->WSALen);
             Log(m_Log);
             return  -1;
         }
         //尝试剥离出一个数据包
         myWSASDATA data = {0};
         data.Lenth = lpPack->WSALen;
         memcpy (data.Buffer, lpPack, lpPack->WSALen);
         //剩下的未处理数据块指针和长度
         Len -= lpPack->WSALen;
         lpHead = lpHead + lpPack->WSALen;
         lpPack = (myWSAPack*)lpHead;
 
         bool  Found =  false ;
         myWSAPack *Pack = (myWSAPack*)data.Buffer;
 
         for  (myCliIt it = m_ClientQueue.begin(); it != m_ClientQueue.end(); ++ it)
         {
             if  ((*it).sClient == sClient)
             {
                 if  ( true  == m_IsHearting && MYWSA_HEARTID == Pack->WSAId)  //心跳包
                 {
                     memset ((*it).Heart, 0,  sizeof ((*it).Heart));  //消除该客户端心跳记录,证明它已回应过
                 }
                 else  //数据包
                 {
                     sprintf_s(data.Addr,  sizeof (data.Addr),  "%s" , (*it).Addr);
                     Found =  true ;
                 }
 
                 break ;
             }
         }
 
         if  ( false  == Found)
         {
             continue ;
         }
 
         m_ReceiveQue.push(data);
         ::PostMessage(m_MainHandle, m_MSGID, m_WPID, MYWSA_SRECEIVE);
     }
 
     return  1;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值