1.演示环境为windows 10 1903

2.演示代码

 #include "pch.h"
#include <iostream>
#include <WinSock2.h>
#include <WS2tcpip.h> #pragma comment(lib, "ws2_32.lib") #define BUFFER_LENGTH 256
#define PACK_LENGTH 11
#define PACK_BUFFER_LENGTH 512 int main()
{
char pack_buffer[PACK_BUFFER_LENGTH] = { };
int pack_buffer_len = ; WORD sv = MAKEWORD(, );
WSAData data;
SOCKET client = INVALID_SOCKET; sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
//addr.sin_addr.S_un.S_addr = InetPtonA(AF_INET, "127.0.0.1", NULL);
addr.sin_port = htons(); while (true)
{
while (true)
{
if (WSAStartup(sv, &data) == )
{
client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (client != INVALID_SOCKET)
{
if (connect(client, (sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
{
printf("connect error. reconnecting...\n");
closesocket(client);
WSACleanup();
Sleep();
}
else {
const char *data = "message from client.\n";
int ret = send(client, data, strlen(data), );
//int ret = send(client, "hello world.\n", strlen("hello world.\n"), 0);
printf("socket connected.\n");
break;
}
}
else {
printf("invalid socket.\n");
}
}
} char buffer[];
while (true)
{
int ret = recv(client, buffer, BUFFER_LENGTH, );
if (ret > )
{
// 粘包情况
buffer[ret] = '\0';
printf(buffer); // 1.数据包定长
//char pack[PACK_LENGTH] = { 0 };
//strncat(pack_buffer, buffer, ret);
//pack_buffer_len += ret;
//while (pack_buffer_len >= PACK_LENGTH)
//{
// strncpy(pack, pack_buffer, PACK_LENGTH);
// char spack[PACK_LENGTH + 1] = { 0 };
// strncpy(spack, pack, PACK_LENGTH);
// spack[PACK_LENGTH] = '\0';
// printf("pack: %s;\r\n", spack); // pack_buffer_len -= PACK_LENGTH;
// strncpy(pack_buffer, pack_buffer + PACK_LENGTH, PACK_BUFFER_LENGTH - PACK_LENGTH);
//} // 2.消息头+消息体 消息头=消息头标识+长度
//strncat(pack_buffer, buffer, ret);
//char *pbrk = NULL;
//do
//{
// pbrk = strpbrk(pack_buffer, "\r\n");
// if (pbrk != NULL)
// {
// int len = pbrk - pack_buffer;
// // 去掉消息头+错误包数据
// strncpy(pack_buffer, pack_buffer + len + 2, PACK_BUFFER_LENGTH - (len + 2));
// len = pack_buffer[0];
// char *pack = (char *)malloc(len + 1);
// strncpy(pack, pack_buffer + 1, len);
// pack[len] = '\0';
// printf("pack: %s;\n", pack);
// free(pack);
// strncpy(pack_buffer, pack_buffer + len + 1, PACK_BUFFER_LENGTH - (len + 1));
// }
//} while (pbrk); // 3.特殊字符作为消息结尾
//strncat(pack_buffer, buffer, ret);
//char *pbrk = NULL;
//do
//{
// pbrk = strstr(pack_buffer, "\r\n");
// //pbrk = strpbrk(pack_buffer, "\r\n");
// if (pbrk != NULL)
// {
// int len = pbrk - pack_buffer;
// char *pack = (char *)malloc(len + 1);
// strncpy(pack, pack_buffer, len);
// pack[len] = '\0';
// printf("pack: %s;\n", pack);
// free(pack);
// strncpy(pack_buffer, pack_buffer + len + 2, PACK_BUFFER_LENGTH - (len + 2));
// }
//} while (pbrk);
}
else if (ret == )
{
printf("Connection closed\n");
closesocket(client);
WSACleanup();
break;
}
else
{
printf("recv failed: %d\n", WSAGetLastError());
closesocket(client);
WSACleanup();
break;
}
}
} closesocket(client);
WSACleanup(); return ;
}

3.不作拆包处理的情况

 // 粘包情况
buffer[ret] = '\0';
printf(buffer); // 1.数据包定长
//char pack[PACK_LENGTH] = { 0 };
//strncat(pack_buffer, buffer, ret);
//pack_buffer_len += ret;
//while (pack_buffer_len >= PACK_LENGTH)
//{
// strncpy(pack, pack_buffer, PACK_LENGTH);
// char spack[PACK_LENGTH + 1] = { 0 };
// strncpy(spack, pack, PACK_LENGTH);
// spack[PACK_LENGTH] = '\0';
// printf("pack: %s;\r\n", spack); // pack_buffer_len -= PACK_LENGTH;
// strncpy(pack_buffer, pack_buffer + PACK_LENGTH, PACK_BUFFER_LENGTH - PACK_LENGTH);
//} // 2.消息头+消息体 消息头=消息头标识+长度
//strncat(pack_buffer, buffer, ret);
//char *pbrk = NULL;
//do
//{
// pbrk = strpbrk(pack_buffer, "\r\n");
// if (pbrk != NULL)
// {
// int len = pbrk - pack_buffer;
// // 去掉消息头+错误包数据
// strncpy(pack_buffer, pack_buffer + len + 2, PACK_BUFFER_LENGTH - (len + 2));
// len = pack_buffer[0];
// char *pack = (char *)malloc(len + 1);
// strncpy(pack, pack_buffer + 1, len);
// pack[len] = '\0';
// printf("pack: %s;\n", pack);
// free(pack);
// strncpy(pack_buffer, pack_buffer + len + 1, PACK_BUFFER_LENGTH - (len + 1));
// }
//} while (pbrk); // 3.特殊字符作为消息结尾
//strncat(pack_buffer, buffer, ret);
//char *pbrk = NULL;
//do
//{
// pbrk = strstr(pack_buffer, "\r\n");
// //pbrk = strpbrk(pack_buffer, "\r\n");
// if (pbrk != NULL)
// {
// int len = pbrk - pack_buffer;
// char *pack = (char *)malloc(len + 1);
// strncpy(pack, pack_buffer, len);
// pack[len] = '\0';
// printf("pack: %s;\n", pack);
// free(pack);
// strncpy(pack_buffer, pack_buffer + len + 2, PACK_BUFFER_LENGTH - (len + 2));
// }
//} while (pbrk);

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

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

socket connected.
123456abc123456abc123456abc123456abc123456abc123456abc123456abc123456abc123456abc123456abc

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

 // 粘包情况
//buffer[ret] = '\0';
//printf(buffer); // 1.数据包定长
char pack[PACK_LENGTH] = { };
strncat(pack_buffer, buffer, ret);
pack_buffer_len += ret;
while (pack_buffer_len >= PACK_LENGTH)
{
strncpy(pack, pack_buffer, PACK_LENGTH);
char spack[PACK_LENGTH + ] = { };
strncpy(spack, pack, PACK_LENGTH);
spack[PACK_LENGTH] = '\0';
printf("pack: %s;\r\n", spack); pack_buffer_len -= PACK_LENGTH;
strncpy(pack_buffer, pack_buffer + PACK_LENGTH, PACK_BUFFER_LENGTH - PACK_LENGTH);
} // 2.消息头+消息体 消息头=消息头标识+长度
//strncat(pack_buffer, buffer, ret);
//char *pbrk = NULL;
//do
//{
// pbrk = strpbrk(pack_buffer, "\r\n");
// if (pbrk != NULL)
// {
// int len = pbrk - pack_buffer;
// // 去掉消息头+错误包数据
// strncpy(pack_buffer, pack_buffer + len + 2, PACK_BUFFER_LENGTH - (len + 2));
// len = pack_buffer[0];
// char *pack = (char *)malloc(len + 1);
// strncpy(pack, pack_buffer + 1, len);
// pack[len] = '\0';
// printf("pack: %s;\n", pack);
// free(pack);
// strncpy(pack_buffer, pack_buffer + len + 1, PACK_BUFFER_LENGTH - (len + 1));
// }
//} while (pbrk); // 3.特殊字符作为消息结尾
//strncat(pack_buffer, buffer, ret);
//char *pbrk = NULL;
//do
//{
// pbrk = strstr(pack_buffer, "\r\n");
// //pbrk = strpbrk(pack_buffer, "\r\n");
// if (pbrk != NULL)
// {
// int len = pbrk - pack_buffer;
// char *pack = (char *)malloc(len + 1);
// strncpy(pack, pack_buffer, len);
// pack[len] = '\0';
// printf("pack: %s;\n", pack);
// free(pack);
// strncpy(pack_buffer, pack_buffer + len + 2, PACK_BUFFER_LENGTH - (len + 2));
// }
//} 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.使用消息头+消息体 消息头=消息头标识+长度

 // 粘包情况
//buffer[ret] = '\0';
//printf(buffer); // 1.数据包定长
//char pack[PACK_LENGTH] = { 0 };
//strncat(pack_buffer, buffer, ret);
//pack_buffer_len += ret;
//while (pack_buffer_len >= PACK_LENGTH)
//{
// strncpy(pack, pack_buffer, PACK_LENGTH);
// char spack[PACK_LENGTH + 1] = { 0 };
// strncpy(spack, pack, PACK_LENGTH);
// spack[PACK_LENGTH] = '\0';
// printf("pack: %s;\r\n", spack); // pack_buffer_len -= PACK_LENGTH;
// strncpy(pack_buffer, pack_buffer + PACK_LENGTH, PACK_BUFFER_LENGTH - PACK_LENGTH);
//} // 2.消息头+消息体 消息头=消息头标识+长度
strncat(pack_buffer, buffer, ret);
char *pbrk = NULL;
do
{
pbrk = strpbrk(pack_buffer, "\r\n");
if (pbrk != NULL)
{
int len = pbrk - pack_buffer;
// 去掉消息头+错误包数据
strncpy(pack_buffer, pack_buffer + len + , PACK_BUFFER_LENGTH - (len + ));
len = pack_buffer[];
char *pack = (char *)malloc(len + );
strncpy(pack, pack_buffer + , len);
pack[len] = '\0';
printf("pack: %s;\n", pack);
free(pack);
strncpy(pack_buffer, pack_buffer + len + , PACK_BUFFER_LENGTH - (len + ));
}
} while (pbrk); // 3.特殊字符作为消息结尾
//strncat(pack_buffer, buffer, ret);
//char *pbrk = NULL;
//do
//{
// pbrk = strstr(pack_buffer, "\r\n");
// //pbrk = strpbrk(pack_buffer, "\r\n");
// if (pbrk != NULL)
// {
// int len = pbrk - pack_buffer;
// char *pack = (char *)malloc(len + 1);
// strncpy(pack, pack_buffer, len);
// pack[len] = '\0';
// printf("pack: %s;\n", pack);
// free(pack);
// strncpy(pack_buffer, pack_buffer + len + 2, PACK_BUFFER_LENGTH - (len + 2));
// }
//} 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.特殊字符作为消息结尾

 // 粘包情况
//buffer[ret] = '\0';
//printf(buffer); // 1.数据包定长
//char pack[PACK_LENGTH] = { 0 };
//strncat(pack_buffer, buffer, ret);
//pack_buffer_len += ret;
//while (pack_buffer_len >= PACK_LENGTH)
//{
// strncpy(pack, pack_buffer, PACK_LENGTH);
// char spack[PACK_LENGTH + 1] = { 0 };
// strncpy(spack, pack, PACK_LENGTH);
// spack[PACK_LENGTH] = '\0';
// printf("pack: %s;\r\n", spack); // pack_buffer_len -= PACK_LENGTH;
// strncpy(pack_buffer, pack_buffer + PACK_LENGTH, PACK_BUFFER_LENGTH - PACK_LENGTH);
//} // 2.消息头+消息体 消息头=消息头标识+长度
//strncat(pack_buffer, buffer, ret);
//char *pbrk = NULL;
//do
//{
// pbrk = strpbrk(pack_buffer, "\r\n");
// if (pbrk != NULL)
// {
// int len = pbrk - pack_buffer;
// // 去掉消息头+错误包数据
// strncpy(pack_buffer, pack_buffer + len + 2, PACK_BUFFER_LENGTH - (len + 2));
// len = pack_buffer[0];
// char *pack = (char *)malloc(len + 1);
// strncpy(pack, pack_buffer + 1, len);
// pack[len] = '\0';
// printf("pack: %s;\n", pack);
// free(pack);
// strncpy(pack_buffer, pack_buffer + len + 1, PACK_BUFFER_LENGTH - (len + 1));
// }
//} while (pbrk); // 3.特殊字符作为消息结尾
strncat(pack_buffer, buffer, ret);
char *pbrk = NULL;
do
{
pbrk = strstr(pack_buffer, "\r\n");
//pbrk = strpbrk(pack_buffer, "\r\n");
if (pbrk != NULL)
{
int len = pbrk - pack_buffer;
char *pack = (char *)malloc(len + );
strncpy(pack, pack_buffer, len);
pack[len] = '\0';
printf("pack: %s;\n", pack);
free(pack);
strncpy(pack_buffer, pack_buffer + len + , PACK_BUFFER_LENGTH - (len + ));
}
} 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常用拆包处理的更多相关文章

  1. 开源基于asio的网络通信框架asio2,支持TCP,UDP,HTTP,RPC,SSL,跨平台,支持可靠UDP,支持TCP自动拆包,TCP数据报模式等

    开源基于asio的网络通信框架asio2,支持TCP,UDP,HTTP,RPC,SSL,跨平台,支持可靠UDP,支持TCP自动拆包,TCP数据报模式等 C++开发网络通信程序时用asio是个不错的选择 ...

  2. TCP常用网络和木马使用端口对照表,常用和不常用端口一览表

    [开始-运行- CMD , 输入 netstat -an 然后回车就可以查看端口] 端口: 服务:Reserved 说明:通常用于分析操作系统.这一方法能够工作是因为在一些系统中“”是无效端口,当你试 ...

  3. netty解决TCP的拆包和粘包的解决办法

    TCP粘包.拆包问题 熟悉tcp编程的可能知道,无论是服务端还是客户端,当我们读取或者发送数据的时候,都需要考虑TCP底层的粘包个拆包机制. tcp是一个“流”协议,所谓流就是没有界限的传输数据,在业 ...

  4. TCP 常用总结

    SO_RCVBUF SO_SNDBUF TCP socket在内核中都有一个发送缓冲区和一个接收缓冲区,不管进程是否读取socket,对端发来的数据都会经由内核接收并且缓存到socket的内核接收缓冲 ...

  5. nagios系列(四)之nagios主动方式监控tcp常用的80/3306等端口监控web/syncd/mysql及url服务

    nagios主动方式监控tcp服务web/syncd/mysql及url cd /usr/local/nagios/libexec/ [root@node4 libexec]# ./check_tcp ...

  6. TCP 粘包/拆包问题

    简介    TCP 是一个’流’协议,所谓流,就是没有界限的一串数据. 大家可以想想河里的流水,是连成一片的.期间并没有分界线, TCP 底层并不了解上层业务数据的具体含义 ,它会根据 TCP 缓冲区 ...

  7. 关于TCP的粘包和拆包

    问题产生 一个完整的业务可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这个就是TCP的拆包和封包问题. 下面可以看一张图,是客户端向服务端发送包: 1. 第一种情况 ...

  8. TCP粘包和拆包问题

    问题产生 一个完整的业务可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这个就是TCP的拆包和封包问题. 下面可以看一张图,是客户端向服务端发送包: 1. 第一种情况 ...

  9. 常用的TCP Option

    当前,TCP常用的Option如下所示———— Kind (Type) Length Name Reference 描述 & 用途 0 1 EOL RFC 793 选项列表结束 1 1 NOP ...

随机推荐

  1. k8s系列---资源指标API及自定义指标API

    不得不说千万不要随意更改版本,我用的1.13的版本,然后学到这一步时,还因yaml文件不同,卡住了很久,然后各种google才找到解决办法  https://www.linuxea.com/2112. ...

  2. k8s系列---部署集群

    docer启动出错 [root@centos-minion yum.repos.d]# systemctl start docker Job for docker.service failed bec ...

  3. centos7上安装docker社区版

    container(容器) docker(集装箱) 容器的优点 1. 启动速度快 2. 节省资源 3. 兼容性高 保证机器正常上网 #ping www.baidu.com CPU需要支持虚拟化 # g ...

  4. 2019IT运维大会上海站 智和信通解析等保2.0支撑

    2019IT运维大会上海站 智和信通解析等保2.0支撑 2019年11月14日上午8:30-12:10,上海锦荣国际大酒店二层锦荣厅

  5. absoulue与relative配合定位盒子居中问题

    如何通过absoulue与relative配合把一个盒子或者是把2个div块同时放到页面中央部分?定位完成后为什么又需要margin-left与margin-top各往回走50%的长度,别忘记用z-i ...

  6. linux中压缩解压缩命令

    目录 gzip gunzip tar(打包压缩) tar(解包解压) zip unzip bzip2 bunzip2 gzip 解释 命令名称:gzip 命令英文原意:GUN zip 命令所在路径:/ ...

  7. ELK学习003:Elasticsearch启动常见问题

    一.Caused by: java.lang.RuntimeException: can not run elasticsearch as root 这个错误,是因为使用root用户启动elastic ...

  8. C#_Excel数据读取与写入_自定义解析封装类_支持设置标题行位置&使用excel表达式收集数据&单元格映射&标题映射&模板文件的参数数据替换

    本篇博客园是被任务所逼,而已有的使用nopi技术的文档技术经验又不支持我需要的应对各种复杂需求的苛刻要求,只能自己造轮子封装了,由于需要应对很多总类型的数据采集需求,因此有了本篇博客的代码封装,下面一 ...

  9. [Python]爬取 游民星空网站 每周精选壁纸(1080高清壁纸) 网络爬虫

    一.检查 首先进入该网站的https://www.gamersky.com/robots.txt页面 给出提示: 弹出错误页面 注: 网络爬虫:自动或人工识别robots.txt,再进行内容爬取 约束 ...

  10. P4735 最大异或和 /【模板】可持久化Trie

    //tire的可持久化 //线段树的可持久化——主席树 //可持久化的前提:本身的拓扑结构在操作时不变 //可以存下来数据结构的所有历史版本 //核心思想:只记录每一个版本与前一个版本不一样的地方 / ...