学习网络编程也有一段时间了,一直听说TCP数据会连包,但一直不知道怎么测试好。最近测试了下:发送方使用对列,将发送的数据存入队列,然后开线程,专门发送。发送多包数据之间不延时。在接收方,他们确实连在一起了。花了点时间,写了一小段代码解决这个问题,其实一共也就4个函数:

 #define FIND_NO_HEAD 1024

 int MyTcpSock::GetPackageSetedLength(char *pHeader)
{
XX_NETPACKET_HEADER *pNetHeader = (XX_NETPACKET_HEADER *)pHeader; return (sizeof(XX_NETPACKET_HEADER) + pNetHeader->packetsize);
} int MyTcpSock::FindHeaderFlag(char *buf,int len)
{
#define FLAGS_NUM 4 int count = ;
char i=;
unsigned char Flags[FLAGS_NUM] = {XX_FLAG1,XX_FLAG2,XX_FLAG3,XX_FLAG4};
XX_NETPACKET_HEADER *pHeader = (XX_NETPACKET_HEADER *)(buf+count); while(count < len)
{
for(i=;i<FLAGS_NUM;i++)
{
if(pHeader->flag == Flags[i])
{
return ((char *)pHeader - buf);
}
} count ++;
pHeader = (XX_NETPACKET_HEADER *)(buf+count);
} return FIND_NO_HEAD;
} void MyTcpSock::ResolveRecievedData(char *buf,int len)
{
char *pUnreslovedData = (char *)buf; //指向待解析的数据的开始
int iUnreslovedDataLen = len; //待解析的数据的长度
int iHeaderPosition = ; //数据头的位置--相对于待解析的数据的起始位置
int iPackageLen = ; //解析出的命令的数据包长度 while(iUnreslovedDataLen > )
{
iHeaderPosition = FindHeaderFlag(pUnreslovedData,iUnreslovedDataLen);
if(iHeaderPosition == FIND_NO_HEAD)
{
TRACE("Find no Header!\n");
Printf(pUnreslovedData,iUnreslovedDataLen);
return ;
}
iPackageLen = this->GetPackageSetedLength((char *)(pUnreslovedData+iHeaderPosition));
if(iPackageLen > iUnreslovedDataLen)
{
TRACE("Package is not full!\n");
Printf(pUnreslovedData,iUnreslovedDataLen);
return ;
} ResolvePackageCmd((char *)(pUnreslovedData+iHeaderPosition),iPackageLen); pUnreslovedData = pUnreslovedData + iHeaderPosition + iPackageLen; //调整指针
iUnreslovedDataLen = iUnreslovedDataLen - iHeaderPosition - iPackageLen;
}
} void MyTcpSock::ResolvePackageCmd(char *buf,int len)
{
XX_NETPACKET_HEADER *pNetHeader = (XX_NETPACKET_HEADER *)buf; //XXX后面就是命令的解析了
}

  以上代码是C++,去掉类就是C。以上代码经过测试,可以解决如下问题:

  数据连包的问题。

  数据发送丢失,比如有包头却丢失了一些数据。后面解析这些命令时,如果以为数据存在,直接用将会出现不可预知的错误。

命令包格式的设计,基本要遵守CLV的格式,C-code命令,L-Length命令长度,V-Value值。

  这里的命令也基本上就是上面的Flag,因为不通命令可能带的值不一样,所以也就必须定义此命令的长度。这在连包处理上非常重要。

处理TCP连包的一小段代码的更多相关文章

  1. 关于PHP的一小段代码求解如下求解"%2\$s"

    <?php$format = "The %2\$s contains %1\$d monkeys";printf($format, 8, "北京");?& ...

  2. 假设写一段代码引导PC开机这段代码是 ? Here is a tiny &quot;OS&quot; :-D

    Hello world -- OS 我找到了华科绍志远博士的相关代码,发现他依据MIT的JOS的boot.S 稍作改动.然后单独剥离出来,能够非常好玩~ 资料下载地址: http://download ...

  3. Netty TCP粘包/拆包问题《一》

    1.使用LineBasedFrameDecoder,StringDecoder解析器进行解决TCP粘包/拆包问题 2.代码搞起: TimeClient:客户端 /* * Copyright 2013- ...

  4. TCP粘包处理通用框架--C代码

    说明:该文紧接上篇博文“ linux epoll机制对TCP 客户端和服务端的监听C代码通用框架实现 ”讲来 (1)TCP粘包处理数据结构设计 #define MAX_MSG_LEN 65535 ty ...

  5. TCP粘"包"问题浅析及解决方案Golang代码实现

    一.粘"包"问题简介 在socket网络编程中,都是端到端通信,客户端端口+客户端IP+服务端端口+服务端IP+传输协议就组成一个可以唯一可以明确的标识一条连接.在TCP的sock ...

  6. [置顶] NS2中对TCP数据包和ACK包的TCP Sink类的主要实现代码详尽剖析--吐血放送

    NS2中对TCP数据包和ACK包的TCP Sink类的主要实现代码详尽剖析,限于个人水平,如有错误请留言指出! TcpSink类的recv()方法: void TcpSink::recv(Packet ...

  7. 6行代码解决golang TCP粘包

    转自:https://studygolang.com/articles/12483 什么是TCP粘包问题以及为什么会产生TCP粘包,本文不加讨论.本文使用golang的bufio.Scanner来实现 ...

  8. TCP数据包的封包和拆包

    //该段博文为引用,非原创. 封包和拆包 作者:fengge8ylf  博客:http://blog.csdn.net/fengge8ylf 对于基于TCP开发的通讯程序,有个很重要的问题需要解决,就 ...

  9. (经典)tcp粘包分析

    转载自csdn:http://blog.csdn.net/zhangxinrun/article/details/6721495 这两天看csdn有一些关于socket粘包,socket缓冲区设置的问 ...

随机推荐

  1. VIJOS 1889 天真的因数分解 ——莫比乌斯函数

    同理BZOJ2440 二分答案,不过这次变成了统计含有平方因子的个数 #include <cmath> #include <cstdio> #include <cstri ...

  2. [luoguP2331] [SCOI2005]最大子矩阵(DP)

    传送门 orz不会做... 一个好理解的做法(n^3*k): 分n=1和n=2两种情况考虑. n=1时,预处理出前缀和sum[]. 设f[i][j]为到达第i格,已经放了j个子矩阵的最大和, 那么每次 ...

  3. Python 可变对象与不可变对象

    1. 不可变(immutable):int.字符串(string).float.(数值型number).元组(tuple) 可变(mutable):字典型(dictionary).列表型(list) ...

  4. 【Vijos1250】最勇敢的机器人(并查集,分组背包DP)

    题意:有N个物品,承重上限为M,有K组物品互斥关系,互斥关系有传递性,即1与2互斥,2与3互斥,1与3也互斥 给出每个物品的花费和价值,求承重上限内的最大价值总和 n<=1000,m<=1 ...

  5. 【Git】Git 本地的撤销修改和删除操作

    一:撤销操作 比如我现在在readme.txt文件里面增加一行 内容为555555555555,我们先通过命令查看如下: 在我未提交之前,我发现添加5555555555555内容有误,所以我得马上恢复 ...

  6. (7)C#连DB2---oledb方式

    1安装客户端 安装DbVisualizer Free 客户端软件 2编目 用 win+r  输入 db2cmd 启动命令行 要远程操作数据库,首先要进行编目,分三个步骤: 1. 在客户端建立服务器端数 ...

  7. Spring的IoC容器-Spring BeanFactory容器

    虽然这个方法已经在3.1之后已经弃用了,但是可以了解一下. 在Spring中,有大量对BeanFactory接口的实现.其中,最常被使用的是XmlBeanFactory类.这个容器从一个XML文件中读 ...

  8. vSphere 6.5 新功能 (7) - 支持 512e 硬盘

    2016-12-11 Newton 长期以来,机械硬盘在储存数据时,一直都是以 512 byte 大小的扇区(Sector)为单位分割进行读写.随着硬盘容量的不断提升,这种古老的分配标准已经越来越不合 ...

  9. Java8 时区DateTime API

    原文:http://www.yiibai.com/java8/java8_zoneddateapi.html 时区日期时间的API正在使用当时区要被考虑时. 让我们来看看他们的操作. 选择使用任何编辑 ...

  10. MySql 初始化权限脚本

    刚装好MySql后无法用客户端工具连接,通过命令行登录后,运行下面的脚本: GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'     IDENTIFIED BY 'y ...