数据封包协议规定:整个数据包包含2字节长度信息+数据包体。2字节长度信息包含本身着2字节。如:数据体是(abcdefg)7个字节,整体封包就是09abcdefg,总共是9个字节的协议

1、netbus接收到数据后发送到static void on_recv_tcp_data(uv_session* s),数据包含在session管理里面s->recv_buf和s->recved两个属性是这个session收取的数据信息

static void on_recv_tcp_data(uv_session* s){unsigned char* pkg_data = (unsigned char*)((s->long_pkg != NULL) ? s->long_pkg : s->recv_buf);while (s->recved > 0){int pkg_size = 0;int head_size = 0;if (!tcp_protocol::read_header(pkg_data, s->recved, &pkg_size, &head_size)){break;  //如果读不到头,就继续收数据}if (s->recved < pkg_size){  //数据不够一个数据包,继续收数据break;}//至少收到了一个完整的数据包unsigned char* raw_data = pkg_data + head_size;     //数据包的起始内存地址,去掉长度on_recv_client_cmd((session*)s, raw_data, pkg_size - head_size);   //处理数据if (s->recved > pkg_size){   //如果recved大于pkg_size,除了这一个完整的包外,还有其他数据,memmove(pkg_data, pkg_data + pkg_size, s->recved - pkg_size);    //处理一个完整数据包后,把后面的未处理数据移动到头部,下一轮循环处理}//recved的数据最少要等于pkg_size,所以recved不可能小于0,如果recved小于pkg_size上边一个条件判断就会中断了s->recved -= pkg_size;if (s->recved == 0 && s->long_pkg != NULL){free(s->long_pkg);s->long_pkg = NULL;s->long_pkg_size = 0;}//end}}

2、pkg_data是因为数据包体可能超过协议长度RECV_LEN,所以会启用long_pkg,来处理很大的包
下面是一个死循环用来处理接收到的数据(大包处理具体请看https://blog.csdn.net/qq_28710983/article/details/83045843这边文章)

3、read_header函数根据封包协议解析出数据包长度信息

bool tcp_protocol::read_header(unsigned char* data, int data_len,int* pkg_size, int* out_head_size){if (data_len < 2){ //没有办法读取包的大小,前两个自己位一个包的长度return false;}*pkg_size = ((data[0]) | (data[1] << 8));*out_head_size = 2;return true;
}

TCP数据包有粘包问题,接收的数据可能有以下几种情况

收到一个完整数据包的情况下(假设收到的数据封包为09abcdefg)

1、read_header是用来读取包长度信息的,因为规定2字节是长度信息,所以如果收到的信息没有2字节就没有办法解析出长度,所以跳出循环继续接收数据,否则就根据前2字节解析出pkg_size和head_size,head_size永远为2字节,这个是规定

2、if (s->recved < pkg_size) 这时解析出的pkg_size是9,s->recved = 9条件通过往下执行

3、前面判断通过说明数据接收完成s->recved = 9,raw_data = pkg_data + head_size ,这里raw_data就是数据包体的内存起始地址,因为前2字节是长度信息,(09abcdefg)用这个为例,假如从100为第一个字母地址,那么数据包的起始地址a就是102,那么raw_data的起始地址就是102

4、前面判断都通过,那么就至少解析到了1整个数据包,就进入 void on_recv_client_cmd(session* s, unsigned char* body, int len)函数处理数据

5、处理完成数据后,判断s->recved > pkg_size除了这个数据包,是否还有其他数据,这里s->recved = 9,pkg_size = 9,条件不通过,往下执行

6、s->recved -= pkg_size  ,  s->recved = 0;

7、while循环条件不成立跳出循环

收到1.5个协议包的情况(09abdefg091234)

1、read_header是用来读取包长度信息的,因为规定2字节是长度信息,所以如果收到的信息没有2字节就没有办法解析出长度,所以跳出循环继续接收数据,否则就根据前2字节解析出pkg_size和head_size,head_size永远为2字节,这个是规定

2、if (s->recved < pkg_size) 这时解析出的pkg_size是9,s->recved = 15条件通过往下执行

3、前面判断通过说明数据接收完成s->recved = 15,raw_data = pkg_data + head_size ,这里raw_data就是数据包体的内存起始地址,因为前2字节是长度信息,(09abcdefg)用这个为例,假如从100为第一个字母地址,那么数据包的起始地址a就是102,那么raw_data的起始地址就是102

4、进入on_recv_client_cmd处理数据

5、处理完成数据后,判断s->recved > pkg_size除了这个数据包,是否还有其他数据,这里s->recved = 15,pkg_size = 9,条件通过,下面是目前内存分布情况

执行memmove函数,memmove(pkg_data, pkg_data + pkg_size, s->recved - pkg_size),前面一个数据封包已经处理好,下次要处理第二个数据封包,on_recv_ws_data每次都是从s->recv_buf的起始位置开始处理,所以需要把第二个封包移动到recv_buf的起始为位置,第二个数据包的起始地址是recv_buf的起始地址100 再加上第一个数据封包的长度9,所以第二个数据封包的起始地址就是recv_buf + pkg_size ,pkg_data就是recv_buf,所以等于pkg_data + pkg_size,移动数据长度是剩下没有处理的数据的长度s->recved - pkg_size = 15 - 9 = 6,移动6个字节,这样就把第二个数据封包移动到s->recv_buf的起始地址

6、s->recved -= pkg_size , s->recved = 6表示还有6个字节长度没有处理完成,继续while循环,当执行完成read_header函数后解析出第二个数据封包长度为9,但是剩余长度只剩下6,还有3字节没有接收完成,所以到if (s->recved < pkg_size)判断的时候跳出while循环,netbus继续接收数据

数据封包解包协议之TCP封包解包相关推荐

  1. wireshark 抓包再利用TCP socket发送包里的payload是可以实现登陆的

    用户密码可被批量破解 在用户使用手机端登录时,对数据进行抓包分析. 多次抓包分析后,可得到几个关键TCP数据包. 根据前面逆向编写出的解密算法,使用socket进行数据发包测试: 可以模拟APK进行用 ...

  2. CS架构--网络通信--osi 协议---套接字socket--粘包

    网络基础之网络协议篇---CS架构--网络通信--osi 协议---套接字socket--粘包 1 C\S 客户端/服务器架构: 1.硬件 C/S架构  (打印机) 2.软件 C/S 架构 互联网中处 ...

  3. 网络基础之网络协议篇---CS架构--网络通信--osi 协议---套接字socket--粘包

    1 C\S 客户端/服务器架构: 1.硬件 C/S架构 (打印机)2.软件 C/S 架构 互联网中处处是C/S架构如黄色网站是服务端,你的浏览器是客户端(B/S架构也是C/S架构的一种)腾讯作为服务端 ...

  4. TCP socket心跳包示例程序

    TCP socket心跳包示例程序_xqhrs232的专栏-CSDN博客_setsockopt 心跳包 原文地址::TCP socket心跳包示例程序_神奕的专栏-CSDN博客_tcp心跳包 相关文章 ...

  5. TCP数据包协议格式详解

    出一个专栏把通信协议搞一下吧,万物互联的根本呀. IP 版本4位:4(二进制0100)表示IPv4,6(二进制0110)表示IPv6 报头长度(单位4byte):因为选项长度不确定,取值范围是5-15 ...

  6. 关于TCP封包、粘包、半包

    关于Tcp封包 很多朋友已经对此作了不少研究,也花费不少心血编写了实现代码和blog文档.当然也充斥着一些各式的评论,自己看了一下,总结一些心得. 首先我们学习一下这些朋友的心得,他们是: http: ...

  7. TCP解决粘包问题(结构数据封包拆包)

    TCP封包拆包 前言 封包 一.包结构 二.封包方法 拆包 总结 前言 TCP协议(Transmission Control Protocol)是一种面向连接的.可靠的.基于字节流的通信协议,即TCP ...

  8. UDP数据包协议格式详解

    源端口目的端口:是0-65535任何数字,在收到请求时系统会为客户端动态分配,0-1023为知名端口号 报文长度(单位4byte):表示udp报头+udp数据总长度,有别于tcp,也没有选项 UDP报 ...

  9. COAP数据包协议格式详解

    Ver:版本编号,占2bit,固定01 T:报文类型,占2bit,CON=00,NON=01,ACK=10,RST=11 CON--需要被确认的请求,如果CON请求被发送,那么对方必须做出响应. NO ...

最新文章

  1. 如何完成从研究型到工程型的转变
  2. JAVA SE学习day_12:集合的排序、队列、栈结构
  3. 关闭SharePoint 2010 customErrors
  4. resource.arsc二进制内容解析 之 RES_TABLE_TYPE_TYPE (Config List)
  5. 40个大数据学习资源,个个是干货,最后7个太给力
  6. 【转】SVM入门(一)SVM的八股简介
  7. 哈工大威海计算机组成原理,哈工大威海计算机组成原理复习.pdf
  8. HTML5 API详解(4):最实用的API DeviceOrientation设备传感器
  9. 经典分享:一份高达555页的技术PPT会是什么样子?
  10. spark需要maven管理吗_使用Eclipse编写Spark应用程序(Scala+Maven)
  11. java补码运算代码_计算机原码、补码、反码与java移位运算符(//)
  12. easypoi/easyExcel导出excel(xls,xlsx)后,文件打开错误或乱码的解决方法
  13. 基于深度学习的人脸表情识别实现
  14. 如何通过网站域名查询服务器地址,如何根据域名查看服务器地址
  15. 论文阅读:(arXiv 2021)Beyond Periodicity: Towards a Unifying Framework for Activations in Coordinate-MLP
  16. 目标追踪——光流法optical flow
  17. 论文评审最大流_关于硕士学位论文评审中出现的问题及其处理
  18. 【程序源代码】微信小程序商城管理系统(java后台+小程序)
  19. 计算机控制双积分系统,双积分式ADC的原理及如何设计
  20. response是什么意思中文_response是什么意思

热门文章

  1. javax.validation
  2. 如果我是你~学会站在别人的角度去说话
  3. ora-27100产生的原因分析
  4. 制造业数字化转型关键问题有哪些?
  5. 【游戏开发创新】当我学了Blender 建模,自制3D电脑桌面,回收站爆发了,把我做的模型都吐了出来(Blender | Unity | FBX)
  6. redis 集群 实操 (史上最全、5w字长文)
  7. 5GHz超频教程:技嘉Z390 AORUS MASTER主板+酷睿i9
  8. 网络系统管理 - C模块 - Centos7.9 - Iptables
  9. visual studio 批量注释与取消批量注释快捷键
  10. 51单片机入门学习 第六天