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粘包拆包常规处理;