TCP常用拆包处理
Posted linxmouse
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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...\\n"); 39 closesocket(client); 40 WSACleanup(); 41 Sleep(1000); 42 43 else 44 const char *data = "message from client.\\n"; 45 int ret = send(client, data, strlen(data), 0); 46 //int ret = send(client, "hello world.\\n", strlen("hello world.\\n"), 0); 47 printf("socket connected.\\n"); 48 break; 49 50 51 else 52 printf("invalid socket.\\n"); 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] = ‘\\0‘; 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] = ‘\\0‘; 77 // printf("pack: %s;\\r\\n", 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, "\\r\\n"); 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] = ‘\\0‘; 98 // printf("pack: %s;\\n", 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, "\\r\\n"); 110 // //pbrk = strpbrk(pack_buffer, "\\r\\n"); 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] = ‘\\0‘; 117 // printf("pack: %s;\\n", 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\\n"); 126 closesocket(client); 127 WSACleanup(); 128 break; 129 130 else 131 132 printf("recv failed: %d\\n", 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] = ‘\\0‘; 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] = ‘\\0‘; 15 // printf("pack: %s;\\r\\n", 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, "\\r\\n"); 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] = ‘\\0‘; 36 // printf("pack: %s;\\n", 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, "\\r\\n"); 48 // //pbrk = strpbrk(pack_buffer, "\\r\\n"); 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] = ‘\\0‘; 55 // printf("pack: %s;\\n", pack); 56 // free(pack); 57 // strncpy(pack_buffer, pack_buffer + len + 2, PACK_BUFFER_LENGTH - (len + 2)); 58 // 59 // while (pbrk);
使用sockettool连续发送一个字符串10次
从输出结果可以看出数据包粘在了一块,出现了粘包
socket connected. 123456abc123456abc123456abc123456abc123456abc123456abc123456abc123456abc123456abc123456abc
4.使用定长数据包,数据包长度设定为11
1 // 粘包情况 2 //buffer[ret] = ‘\\0‘; 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] = ‘\\0‘; 15 printf("pack: %s;\\r\\n", 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, "\\r\\n"); 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] = ‘\\0‘; 36 // printf("pack: %s;\\n", 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, "\\r\\n"); 48 // //pbrk = strpbrk(pack_buffer, "\\r\\n"); 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] = ‘\\0‘; 55 // printf("pack: %s;\\n", pack); 56 // free(pack); 57 // strncpy(pack_buffer, pack_buffer + len + 2, PACK_BUFFER_LENGTH - (len + 2)); 58 // 59 // while (pbrk);
使用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] = ‘\\0‘; 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] = ‘\\0‘; 15 // printf("pack: %s;\\r\\n", 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, "\\r\\n"); 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] = ‘\\0‘; 36 printf("pack: %s;\\n", 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, "\\r\\n"); 48 // //pbrk = strpbrk(pack_buffer, "\\r\\n"); 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] = ‘\\0‘; 55 // printf("pack: %s;\\n", pack); 56 // free(pack); 57 // strncpy(pack_buffer, pack_buffer + len + 2, PACK_BUFFER_LENGTH - (len + 2)); 58 // 59 // while (pbrk);
使用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] = ‘\\0‘; 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] = ‘\\0‘; 15 // printf("pack: %s;\\r\\n", 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, "\\r\\n"); 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] = ‘\\0‘; 36 // printf("pack: %s;\\n", 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, "\\r\\n"); 48 //pbrk = strpbrk(pack_buffer, "\\r\\n"); 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] = ‘\\0‘; 55 printf("pack: %s;\\n", pack); 56 free(pack); 57 strncpy(pack_buffer, pack_buffer + len + 2, PACK_BUFFER_LENGTH - (len + 2)); 58 59 while (pbrk);
使用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粘包拆包常规处理;
以上是关于TCP常用拆包处理的主要内容,如果未能解决你的问题,请参考以下文章