TCP常用拆包处理
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常用拆包处理的更多相关文章
- 开源基于asio的网络通信框架asio2,支持TCP,UDP,HTTP,RPC,SSL,跨平台,支持可靠UDP,支持TCP自动拆包,TCP数据报模式等
开源基于asio的网络通信框架asio2,支持TCP,UDP,HTTP,RPC,SSL,跨平台,支持可靠UDP,支持TCP自动拆包,TCP数据报模式等 C++开发网络通信程序时用asio是个不错的选择 ...
- TCP常用网络和木马使用端口对照表,常用和不常用端口一览表
[开始-运行- CMD , 输入 netstat -an 然后回车就可以查看端口] 端口: 服务:Reserved 说明:通常用于分析操作系统.这一方法能够工作是因为在一些系统中“”是无效端口,当你试 ...
- netty解决TCP的拆包和粘包的解决办法
TCP粘包.拆包问题 熟悉tcp编程的可能知道,无论是服务端还是客户端,当我们读取或者发送数据的时候,都需要考虑TCP底层的粘包个拆包机制. tcp是一个“流”协议,所谓流就是没有界限的传输数据,在业 ...
- TCP 常用总结
SO_RCVBUF SO_SNDBUF TCP socket在内核中都有一个发送缓冲区和一个接收缓冲区,不管进程是否读取socket,对端发来的数据都会经由内核接收并且缓存到socket的内核接收缓冲 ...
- 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 ...
- TCP 粘包/拆包问题
简介 TCP 是一个’流’协议,所谓流,就是没有界限的一串数据. 大家可以想想河里的流水,是连成一片的.期间并没有分界线, TCP 底层并不了解上层业务数据的具体含义 ,它会根据 TCP 缓冲区 ...
- 关于TCP的粘包和拆包
问题产生 一个完整的业务可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这个就是TCP的拆包和封包问题. 下面可以看一张图,是客户端向服务端发送包: 1. 第一种情况 ...
- TCP粘包和拆包问题
问题产生 一个完整的业务可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这个就是TCP的拆包和封包问题. 下面可以看一张图,是客户端向服务端发送包: 1. 第一种情况 ...
- 常用的TCP Option
当前,TCP常用的Option如下所示———— Kind (Type) Length Name Reference 描述 & 用途 0 1 EOL RFC 793 选项列表结束 1 1 NOP ...
随机推荐
- k8s系列----索引
day1:k8s集群准备搭建和相关介绍 day2:k8spod介绍与创建 day3:k8sService介绍及创建 day4:ingress资源和ingress-controller day5:存储卷 ...
- Keepalived 配置文件
keepalived的配置文件: keepalived只有一个配置文件keepalived.conf,里面主要包括以下几个配置区域,分别是global_defs. 全局定义及 ...
- Linux 查看CPU、内存、机器型号等硬件信息
# 查看CPU信息 #查看CPU信息(型号) [root@localhost ~]# cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c 32 ...
- [Redis-Python]发布订阅通过Redis异步发送邮件
接收订阅 #!/usr/bin/env pyhton # coding:utf-8 # @Time : 2020-02-16 21:36 # @Author : LeoShi # @Site : # ...
- Yet Another Broken Keyboard[双指针]
题目大意: 求贡献,已知公式n*(n+1)/2,求总和 收获: long long的转换技巧只能在乘或除上进行 题目链接 #include<bits/stdc++.h> typedef l ...
- python随用随学20200220-异步IO
啥是异步IO 众所周知,CPU速度太快,磁盘,网络等IO跟不上. 而程序一旦遇到IO的时候,就需要等IO完成才能进行才能进行下一步的操作. 严重拖累了程序速度. 因为一个IO操作就阻塞了当前线程,导致 ...
- 11种常用css样式学习大结局滚动条与显示隐藏
滚动条展示 overflow-x: hidden;/*是否对内容的左/右边缘进行裁剪*/overflow-y: hidden;/*是否对内容的上/下边缘进行裁剪*/overflow:scroll;/* ...
- nodejs下载网页所有图片
前言 昨天一番发了一篇批量下载手机壁纸的文章,分享了抓取到的美图给小伙伴,然后一番就美美的去碎觉了. 早上起来看到有小伙伴在日更群里说有没有狗哥的?憨憨的一番以为就是狗的图片,于是就发了几张昨天抓取的 ...
- 「Flink」Flink的状态管理与容错
在Flink中的每个函数和运算符都是有状态的.在处理过程中可以用状态来存储数据,这样可以利用状态来构建复杂操作.为了让状态容错,Flink需要设置checkpoint状态.Flink程序是通过chec ...
- 静态SRAM芯片工作原理
下面谈谈当存储字节的过程是怎样的:下面的示意图显示的也仅仅是最简单状态下的情况,当内存条上仅剩一个RAM芯片的情况.对于X86处理器,它通过地址总线发出一个具有22位二进制数字的地址编码--其中11位 ...