zoukankan      html  css  js  c++  java
  • TCP常用拆包处理

    1.演示环境为windows 10 1903

    2.演示代码

      1 #include "pch.h"
      2 #include <iostream>
      3 #include <WinSock2.h>
      4 #include <WS2tcpip.h>
      5 
      6 #pragma comment(lib, "ws2_32.lib")
      7 
      8 #define BUFFER_LENGTH                256
      9 #define PACK_LENGTH                    11
     10 #define PACK_BUFFER_LENGTH            512
     11 
     12 int main()
     13 {
     14     char pack_buffer[PACK_BUFFER_LENGTH] = { 0 };
     15     int pack_buffer_len = 0;
     16 
     17     WORD sv = MAKEWORD(2, 2);
     18     WSAData data;
     19     SOCKET client = INVALID_SOCKET;
     20 
     21     sockaddr_in addr;
     22     addr.sin_family = AF_INET;
     23     addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
     24     //addr.sin_addr.S_un.S_addr = InetPtonA(AF_INET, "127.0.0.1", NULL);
     25     addr.sin_port = htons(8080);
     26 
     27     while (true)
     28     {
     29         while (true)
     30         {
     31             if (WSAStartup(sv, &data) == 0)
     32             {
     33                 client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
     34                 if (client != INVALID_SOCKET)
     35                 {
     36                     if (connect(client, (sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
     37                     {
     38                         printf("connect error. reconnecting...
    ");
     39                         closesocket(client);
     40                         WSACleanup();
     41                         Sleep(1000);
     42                     }
     43                     else {
     44                         const char *data = "message from client.
    ";
     45                         int ret = send(client, data, strlen(data), 0);
     46                         //int ret = send(client, "hello world.
    ", strlen("hello world.
    "), 0);
     47                         printf("socket connected.
    ");
     48                         break;
     49                     }
     50                 }
     51                 else {
     52                     printf("invalid socket.
    ");
     53                 }
     54             }
     55         }
     56 
     57         char buffer[255];
     58         while (true)
     59         {
     60             int ret = recv(client, buffer, BUFFER_LENGTH, 0);
     61             if (ret > 0)
     62             {
     63                 // 粘包情况
     64                 buffer[ret] = '';
     65                 printf(buffer);
     66 
     67                 // 1.数据包定长
     68                 //char pack[PACK_LENGTH] = { 0 };
     69                 //strncat(pack_buffer, buffer, ret);
     70                 //pack_buffer_len += ret;
     71                 //while (pack_buffer_len >= PACK_LENGTH)
     72                 //{
     73                 //    strncpy(pack, pack_buffer, PACK_LENGTH);
     74                 //    char spack[PACK_LENGTH + 1] = { 0 };
     75                 //    strncpy(spack, pack, PACK_LENGTH);
     76                 //    spack[PACK_LENGTH] = '';
     77                 //    printf("pack: %s;
    ", spack);
     78 
     79                 //    pack_buffer_len -= PACK_LENGTH;
     80                 //    strncpy(pack_buffer, pack_buffer + PACK_LENGTH, PACK_BUFFER_LENGTH - PACK_LENGTH);
     81                 //}
     82 
     83                 // 2.消息头+消息体 消息头=消息头标识+长度
     84                 //strncat(pack_buffer, buffer, ret);
     85                 //char *pbrk = NULL;
     86                 //do
     87                 //{
     88                 //    pbrk = strpbrk(pack_buffer, "
    ");                
     89                 //    if (pbrk != NULL)
     90                 //    {
     91                 //        int len = pbrk - pack_buffer;
     92                 //        // 去掉消息头+错误包数据
     93                 //        strncpy(pack_buffer, pack_buffer + len + 2, PACK_BUFFER_LENGTH - (len + 2));
     94                 //        len = pack_buffer[0];
     95                 //        char *pack = (char *)malloc(len + 1);
     96                 //        strncpy(pack, pack_buffer + 1, len);
     97                 //        pack[len] = '';
     98                 //        printf("pack: %s;
    ", pack);
     99                 //        free(pack);
    100                 //        strncpy(pack_buffer, pack_buffer + len + 1, PACK_BUFFER_LENGTH - (len + 1));
    101                 //    }
    102                 //} while (pbrk);
    103 
    104                 // 3.特殊字符作为消息结尾
    105                 //strncat(pack_buffer, buffer, ret);
    106                 //char *pbrk = NULL;
    107                 //do
    108                 //{
    109                 //    pbrk = strstr(pack_buffer, "
    ");
    110                 //    //pbrk = strpbrk(pack_buffer, "
    ");
    111                 //    if (pbrk != NULL)
    112                 //    {
    113                 //        int len = pbrk - pack_buffer;
    114                 //        char *pack = (char *)malloc(len + 1);
    115                 //        strncpy(pack, pack_buffer, len);
    116                 //        pack[len] = '';
    117                 //        printf("pack: %s;
    ", pack);
    118                 //        free(pack);
    119                 //        strncpy(pack_buffer, pack_buffer + len + 2, PACK_BUFFER_LENGTH - (len + 2));
    120                 //    }
    121                 //} while (pbrk);
    122             }
    123             else if (ret == 0)
    124             {
    125                 printf("Connection closed
    ");
    126                 closesocket(client);
    127                 WSACleanup();
    128                 break;
    129             }
    130             else
    131             {
    132                 printf("recv failed: %d
    ", WSAGetLastError());
    133                 closesocket(client);
    134                 WSACleanup();
    135                 break;
    136             }
    137         }
    138     }
    139 
    140     closesocket(client);
    141     WSACleanup();
    142 
    143     return 0;
    144 }

    3.不作拆包处理的情况

     1 // 粘包情况
     2                 buffer[ret] = '';
     3                 printf(buffer);
     4 
     5                 // 1.数据包定长
     6                 //char pack[PACK_LENGTH] = { 0 };
     7                 //strncat(pack_buffer, buffer, ret);
     8                 //pack_buffer_len += ret;
     9                 //while (pack_buffer_len >= PACK_LENGTH)
    10                 //{
    11                 //    strncpy(pack, pack_buffer, PACK_LENGTH);
    12                 //    char spack[PACK_LENGTH + 1] = { 0 };
    13                 //    strncpy(spack, pack, PACK_LENGTH);
    14                 //    spack[PACK_LENGTH] = '';
    15                 //    printf("pack: %s;
    ", spack);
    16 
    17                 //    pack_buffer_len -= PACK_LENGTH;
    18                 //    strncpy(pack_buffer, pack_buffer + PACK_LENGTH, PACK_BUFFER_LENGTH - PACK_LENGTH);
    19                 //}
    20 
    21                 // 2.消息头+消息体 消息头=消息头标识+长度
    22                 //strncat(pack_buffer, buffer, ret);
    23                 //char *pbrk = NULL;
    24                 //do
    25                 //{
    26                 //    pbrk = strpbrk(pack_buffer, "
    ");                
    27                 //    if (pbrk != NULL)
    28                 //    {
    29                 //        int len = pbrk - pack_buffer;
    30                 //        // 去掉消息头+错误包数据
    31                 //        strncpy(pack_buffer, pack_buffer + len + 2, PACK_BUFFER_LENGTH - (len + 2));
    32                 //        len = pack_buffer[0];
    33                 //        char *pack = (char *)malloc(len + 1);
    34                 //        strncpy(pack, pack_buffer + 1, len);
    35                 //        pack[len] = '';
    36                 //        printf("pack: %s;
    ", pack);
    37                 //        free(pack);
    38                 //        strncpy(pack_buffer, pack_buffer + len + 1, PACK_BUFFER_LENGTH - (len + 1));
    39                 //    }
    40                 //} while (pbrk);
    41 
    42                 // 3.特殊字符作为消息结尾
    43                 //strncat(pack_buffer, buffer, ret);
    44                 //char *pbrk = NULL;
    45                 //do
    46                 //{
    47                 //    pbrk = strstr(pack_buffer, "
    ");
    48                 //    //pbrk = strpbrk(pack_buffer, "
    ");
    49                 //    if (pbrk != NULL)
    50                 //    {
    51                 //        int len = pbrk - pack_buffer;
    52                 //        char *pack = (char *)malloc(len + 1);
    53                 //        strncpy(pack, pack_buffer, len);
    54                 //        pack[len] = '';
    55                 //        printf("pack: %s;
    ", pack);
    56                 //        free(pack);
    57                 //        strncpy(pack_buffer, pack_buffer + len + 2, PACK_BUFFER_LENGTH - (len + 2));
    58                 //    }
    59                 //} while (pbrk);
    View Code

    使用sockettool连续发送一个字符串10次

    从输出结果可以看出数据包粘在了一块,出现了粘包

    socket connected.
    123456abc123456abc123456abc123456abc123456abc123456abc123456abc123456abc123456abc123456abc
    

    4.使用定长数据包,数据包长度设定为11

     1 // 粘包情况
     2                 //buffer[ret] = '';
     3                 //printf(buffer);
     4 
     5                 // 1.数据包定长
     6                 char pack[PACK_LENGTH] = { 0 };
     7                 strncat(pack_buffer, buffer, ret);
     8                 pack_buffer_len += ret;
     9                 while (pack_buffer_len >= PACK_LENGTH)
    10                 {
    11                     strncpy(pack, pack_buffer, PACK_LENGTH);
    12                     char spack[PACK_LENGTH + 1] = { 0 };
    13                     strncpy(spack, pack, PACK_LENGTH);
    14                     spack[PACK_LENGTH] = '';
    15                     printf("pack: %s;
    ", spack);
    16 
    17                     pack_buffer_len -= PACK_LENGTH;
    18                     strncpy(pack_buffer, pack_buffer + PACK_LENGTH, PACK_BUFFER_LENGTH - PACK_LENGTH);
    19                 }
    20 
    21                 // 2.消息头+消息体 消息头=消息头标识+长度
    22                 //strncat(pack_buffer, buffer, ret);
    23                 //char *pbrk = NULL;
    24                 //do
    25                 //{
    26                 //    pbrk = strpbrk(pack_buffer, "
    ");                
    27                 //    if (pbrk != NULL)
    28                 //    {
    29                 //        int len = pbrk - pack_buffer;
    30                 //        // 去掉消息头+错误包数据
    31                 //        strncpy(pack_buffer, pack_buffer + len + 2, PACK_BUFFER_LENGTH - (len + 2));
    32                 //        len = pack_buffer[0];
    33                 //        char *pack = (char *)malloc(len + 1);
    34                 //        strncpy(pack, pack_buffer + 1, len);
    35                 //        pack[len] = '';
    36                 //        printf("pack: %s;
    ", pack);
    37                 //        free(pack);
    38                 //        strncpy(pack_buffer, pack_buffer + len + 1, PACK_BUFFER_LENGTH - (len + 1));
    39                 //    }
    40                 //} while (pbrk);
    41 
    42                 // 3.特殊字符作为消息结尾
    43                 //strncat(pack_buffer, buffer, ret);
    44                 //char *pbrk = NULL;
    45                 //do
    46                 //{
    47                 //    pbrk = strstr(pack_buffer, "
    ");
    48                 //    //pbrk = strpbrk(pack_buffer, "
    ");
    49                 //    if (pbrk != NULL)
    50                 //    {
    51                 //        int len = pbrk - pack_buffer;
    52                 //        char *pack = (char *)malloc(len + 1);
    53                 //        strncpy(pack, pack_buffer, len);
    54                 //        pack[len] = '';
    55                 //        printf("pack: %s;
    ", pack);
    56                 //        free(pack);
    57                 //        strncpy(pack_buffer, pack_buffer + len + 2, PACK_BUFFER_LENGTH - (len + 2));
    58                 //    }
    59                 //} while (pbrk);
    View Code

    使用sockettool连续发送一个长度为11的数据包10次

    从输出结果可以看出对数据包按自己要求进行了拆包处理

    socket connected.
    pack: 1234567890a;
    pack: 1234567890a;
    pack: 1234567890a;
    pack: 1234567890a;
    pack: 1234567890a;
    pack: 1234567890a;
    pack: 1234567890a;
    pack: 1234567890a;
    pack: 1234567890a;
    pack: 1234567890a;
    

    5.使用消息头+消息体 消息头=消息头标识+长度

     1 // 粘包情况
     2                 //buffer[ret] = '';
     3                 //printf(buffer);
     4 
     5                 // 1.数据包定长
     6                 //char pack[PACK_LENGTH] = { 0 };
     7                 //strncat(pack_buffer, buffer, ret);
     8                 //pack_buffer_len += ret;
     9                 //while (pack_buffer_len >= PACK_LENGTH)
    10                 //{
    11                 //    strncpy(pack, pack_buffer, PACK_LENGTH);
    12                 //    char spack[PACK_LENGTH + 1] = { 0 };
    13                 //    strncpy(spack, pack, PACK_LENGTH);
    14                 //    spack[PACK_LENGTH] = '';
    15                 //    printf("pack: %s;
    ", spack);
    16 
    17                 //    pack_buffer_len -= PACK_LENGTH;
    18                 //    strncpy(pack_buffer, pack_buffer + PACK_LENGTH, PACK_BUFFER_LENGTH - PACK_LENGTH);
    19                 //}
    20 
    21                 // 2.消息头+消息体 消息头=消息头标识+长度
    22                 strncat(pack_buffer, buffer, ret);
    23                 char *pbrk = NULL;
    24                 do
    25                 {
    26                     pbrk = strpbrk(pack_buffer, "
    ");                
    27                     if (pbrk != NULL)
    28                     {
    29                         int len = pbrk - pack_buffer;
    30                         // 去掉消息头+错误包数据
    31                         strncpy(pack_buffer, pack_buffer + len + 2, PACK_BUFFER_LENGTH - (len + 2));
    32                         len = pack_buffer[0];
    33                         char *pack = (char *)malloc(len + 1);
    34                         strncpy(pack, pack_buffer + 1, len);
    35                         pack[len] = '';
    36                         printf("pack: %s;
    ", pack);
    37                         free(pack);
    38                         strncpy(pack_buffer, pack_buffer + len + 1, PACK_BUFFER_LENGTH - (len + 1));
    39                     }
    40                 } while (pbrk);
    41 
    42                 // 3.特殊字符作为消息结尾
    43                 //strncat(pack_buffer, buffer, ret);
    44                 //char *pbrk = NULL;
    45                 //do
    46                 //{
    47                 //    pbrk = strstr(pack_buffer, "
    ");
    48                 //    //pbrk = strpbrk(pack_buffer, "
    ");
    49                 //    if (pbrk != NULL)
    50                 //    {
    51                 //        int len = pbrk - pack_buffer;
    52                 //        char *pack = (char *)malloc(len + 1);
    53                 //        strncpy(pack, pack_buffer, len);
    54                 //        pack[len] = '';
    55                 //        printf("pack: %s;
    ", pack);
    56                 //        free(pack);
    57                 //        strncpy(pack_buffer, pack_buffer + len + 2, PACK_BUFFER_LENGTH - (len + 2));
    58                 //    }
    59                 //} while (pbrk);
    View Code

    使用sockettool连续发送数据包 回车换行+长度5+字符串12345 10次

    从输出结果可以看出对数据包按自己要求进行了拆包处理

    socket connected.
    pack: 12345;
    pack: 12345;
    pack: 12345;
    pack: 12345;
    pack: 12345;
    pack: 12345;
    pack: 12345;
    pack: 12345;
    pack: 12345;
    pack: 12345;
    

    6.特殊字符作为消息结尾

     1 // 粘包情况
     2                 //buffer[ret] = '';
     3                 //printf(buffer);
     4 
     5                 // 1.数据包定长
     6                 //char pack[PACK_LENGTH] = { 0 };
     7                 //strncat(pack_buffer, buffer, ret);
     8                 //pack_buffer_len += ret;
     9                 //while (pack_buffer_len >= PACK_LENGTH)
    10                 //{
    11                 //    strncpy(pack, pack_buffer, PACK_LENGTH);
    12                 //    char spack[PACK_LENGTH + 1] = { 0 };
    13                 //    strncpy(spack, pack, PACK_LENGTH);
    14                 //    spack[PACK_LENGTH] = '';
    15                 //    printf("pack: %s;
    ", spack);
    16 
    17                 //    pack_buffer_len -= PACK_LENGTH;
    18                 //    strncpy(pack_buffer, pack_buffer + PACK_LENGTH, PACK_BUFFER_LENGTH - PACK_LENGTH);
    19                 //}
    20 
    21                 // 2.消息头+消息体 消息头=消息头标识+长度
    22                 //strncat(pack_buffer, buffer, ret);
    23                 //char *pbrk = NULL;
    24                 //do
    25                 //{
    26                 //    pbrk = strpbrk(pack_buffer, "
    ");                
    27                 //    if (pbrk != NULL)
    28                 //    {
    29                 //        int len = pbrk - pack_buffer;
    30                 //        // 去掉消息头+错误包数据
    31                 //        strncpy(pack_buffer, pack_buffer + len + 2, PACK_BUFFER_LENGTH - (len + 2));
    32                 //        len = pack_buffer[0];
    33                 //        char *pack = (char *)malloc(len + 1);
    34                 //        strncpy(pack, pack_buffer + 1, len);
    35                 //        pack[len] = '';
    36                 //        printf("pack: %s;
    ", pack);
    37                 //        free(pack);
    38                 //        strncpy(pack_buffer, pack_buffer + len + 1, PACK_BUFFER_LENGTH - (len + 1));
    39                 //    }
    40                 //} while (pbrk);
    41 
    42                 // 3.特殊字符作为消息结尾
    43                 strncat(pack_buffer, buffer, ret);
    44                 char *pbrk = NULL;
    45                 do
    46                 {
    47                     pbrk = strstr(pack_buffer, "
    ");
    48                     //pbrk = strpbrk(pack_buffer, "
    ");
    49                     if (pbrk != NULL)
    50                     {
    51                         int len = pbrk - pack_buffer;
    52                         char *pack = (char *)malloc(len + 1);
    53                         strncpy(pack, pack_buffer, len);
    54                         pack[len] = '';
    55                         printf("pack: %s;
    ", pack);
    56                         free(pack);
    57                         strncpy(pack_buffer, pack_buffer + len + 2, PACK_BUFFER_LENGTH - (len + 2));
    58                     }
    59                 } while (pbrk);
    View Code

    使用sockettool连续发送数据包 123456789abc+回车换行 和 tcp粘包拆包常规处理+回车换行 10次

    从输出结果可以看出对数据包按自己要求进行了拆包处理

    socket connected.
    pack: 123456789abc;
    pack: tcp粘包拆包常规处理;
    pack: 123456789abc;
    pack: tcp粘包拆包常规处理;
    pack: 123456789abc;
    pack: tcp粘包拆包常规处理;
    pack: 123456789abc;
    pack: tcp粘包拆包常规处理;
    pack: 123456789abc;
    pack: tcp粘包拆包常规处理;
    pack: 123456789abc;
    pack: tcp粘包拆包常规处理;
    pack: 123456789abc;
    pack: tcp粘包拆包常规处理;
    pack: 123456789abc;
    pack: tcp粘包拆包常规处理;
    pack: 123456789abc;
    pack: tcp粘包拆包常规处理;
    pack: 123456789abc;
    pack: tcp粘包拆包常规处理;
    
  • 相关阅读:
    Teamplate Workflow Architecture(Teamplate工作流架构)
    Las Vegas拉斯维加斯(赌城)游记
    初步尝试Teamplate Workflow Web Part for SharePoint Portal Server
    灵活管理Remote Objects生存期(lifetime)
    Wincv.exe类查看器工具(Class Viewer)
    重构(Refactoring)技巧读书笔记 之二
    重构(Refactoring)技巧读书笔记 之一
    尝试RemotingSqlHelper的若干问题
    关于ADO.Net连接池(Connection Pool)的一些个人见解
    SQL Server 最佳实践分析器使用小结
  • 原文地址:https://www.cnblogs.com/linxmouse/p/11590559.html
Copyright © 2011-2022 走看看