关于TCP/IP网络传输粘包的问题,请帮帮忙!!

phf 2003-04-02 09:48:53
本人用TCP/IP协议开发一网络传输工具,传输的内容主要是一些字符串,但有一定格式的,比如:

部门ID + 部门名称

又或者
用户ID + 部门ID + 用户名称


也就是说我有很多格式的包要在网络中传输。
但我发现有时候(很多时候)会出现粘包的问题。
也就是说,服务器端发送了:
部门ID + 部门名称 后马上发送 用户ID + 部门ID + 用户名称

这样客户端每次接受到两个包,内容为
部门ID + 部门名称 + 用户ID + 部门ID + 用户名称
但客户端是按每一次接收一个包来处理,也就是说这样会丢掉了一个用户信息包。

请问各位有没有碰到这样的问题,有没有什么好的解决方法?
...全文
160 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
phf 2003-04-08
  • 打赏
  • 举报
回复
help
phf 2003-04-07
  • 打赏
  • 举报
回复
谢谢 cdsnti(cdsnti):
您的方法不错,不过我服务器端是java,客户端是c++ builder,所以可能不太适合,不过我想利用你的思想应该可以实现。

qiuafa 2003-04-07
  • 打赏
  • 举报
回复
up
cdsnti 2003-04-05
  • 打赏
  • 举报
回复
不要用 sendtext(), 你用发送数据流的方法,在接收端定义一个缓冲区,
再定义一个通信传输的数据包结构,一次接收时可能数据包不完整,你需要自己处理
typedef struct{
int PacketLen;
int PacketType; //自定义发送包的类型也就是 Buffer 中的数据结构
char Buffer[4096]; //根据实际情况调整
}COMMUNCTIONPACKET;

typedef struct{
char DeptID[20];
char DeptName[50];
}DEPARTMENT;

typedef struct{
char UserID[20];
char DeptID[20];
char UserName[50];
}USERINFO;

USERINFO UserInfo;
COMMUNCTIONPACKET CommuPack;

memset( &UserInfo, 0, sizeof(USERINFO) );
.............
memset( &CommuPack, 0, sizeof(COMMUNCTIONPACKET) );
CommuPack.PackType = 2;
CommuPack.PacketLen = sizeof(USERINFO);
mepcpy( CommuPack.Buffer, &UserInfo, sizeof(USERINFO) );

int sendlen = sizeof(int)*2 + CommuPack.PacketLen;
while( ... ){
//直到全部发送完毕
send( SOCKET, (char *)&CommuPack, sendlen, 0 );
}

这是发送方的处理,接收方定义相同结构,要对接收数据包的完整性
进行处理,一次接收时可能数据包不完整.
phf 2003-04-04
  • 打赏
  • 举报
回复
谢谢 StockViews(股多视) !!
能再详细点说说吗?
StockViews 2003-04-04
  • 打赏
  • 举报
回复
在Client端建立一个数据队列,接收到的数据都从队列中压,处理的模块慢慢地读出来。
netsys2 2003-04-03
  • 打赏
  • 举报
回复
我说的是SERVER端的处理!
如果CLINET端也是可能一次收到多个回应则应该按SERVER相同办法处理
phf 2003-04-03
  • 打赏
  • 举报
回复
谢谢!!
pp616 2003-04-02
  • 打赏
  • 举报
回复
没必要一次发一个啊。可以多大几个。
发这些结构
typedef struct _phfInfoHead
{
int PackType //数据块类型
int PackNum //包含多少个数据结构
}PhfInfoHead;
typedef struct _phfInfoA
{
long deptID;
char deptName[需要的大小]
}PhfInfoA;
typedef struct _phfInfoB
{
long userID;
long deptID;
char deptName[需要的大小]
}PhfInfoB;


Lo 2003-04-02
  • 打赏
  • 举报
回复
Tcp连接是不保护消息边界的协议,UDP是保护消息边界的。
也就是说,Tcp的接收端在接收的时候,会一次性把网络堆栈里的数据全部读取出来,当然前提是你提供的缓冲区要足够大。

用Tcp时,要自己去处理多条消息一同读取的问题,你可以在每个发送的Tcp包前包含一个长度,在接收方居然每个包的长度再来把收到的包分包。
phf 2003-04-02
  • 打赏
  • 举报
回复
help
phf 2003-04-02
  • 打赏
  • 举报
回复
谢谢各位!!
to netsys2(来电) :
你说的是client的处理吗?如果不是哪client的处理方法呢?
麻烦各位了,分可以大大的给!:)
HUANG_JH 2003-04-02
  • 打赏
  • 举报
回复
一般来说可以自定义一个包头如
@HEAD@ + 部门ID + 部门名称
@HEAD@ + 用户ID + 部门ID + 用户名称
这样就可以知道2个@HEAD@ 之间就是一个完整的包
粘包就不是问题了

@HEAD@ + 部门ID + 部门名称 + @HEAD@ + 用户ID + 部门ID + 用户名称

而且实际上网络忙的时候可能还会有这样的状况

第1包
@HEAD@ + 部门ID + 部门名称 + @HEAD@ + 用户ID

第2包
部门ID + 用户名称


要通过自定义包头来解决不完整包的问题


hait 2003-04-02
  • 打赏
  • 举报
回复
tcp/ip通讯中粘包,碎片包都是可能出现的。
1、 可以按 楼上的方法处理。
2、防止粘包,可以在发送端没发送一个包后,sleep 一下。这样就可以保证每次只接收一个包。但这样的效率受些影响。每秒发送的数据包受到限制。
netsys2 2003-04-02
  • 打赏
  • 举报
回复
会出现碎片包情况,必须按上面的方法处理
netsys2 2003-04-02
  • 打赏
  • 举报
回复
Server处理标准流程:


1)接受全部数据到缓冲BUF
2)检查同步符,根据结构定义从同步符起分割一个包
3)检查该包是否合法,是则到下一步,否则丢弃将指针移到同步符后返回2步
4)处理该包,接收缓冲BUF指针下移一个包
5)从2开始循环,直到剩余不够一个包
6)将剩余填入接收BUF初始,接收BU指针也作处理
7)如果再有数据从1开始循环,新接收数据从上面剩余开始存放
。。。
phf 2003-04-02
  • 打赏
  • 举报
回复
非常谢谢几位大虾!!
是这样的,我的服务器端是用java编写,客户端用c++ builder写,所以我想没办法发送结构等。
可能只好采用分包处理的方式了。
我发送的内容是以文本方式的(sendtext()),把每个结构的每个字段用一个特殊的符号分割开的。

to:netsys2
我想问一下你开发的时候一般是怎么做切割和分包处理的。(打个比喻,如果QQ用TCP来传输,它应该怎么保证把每包分开呢?



还有想问一下,会不会出现客户端只收到1.5个包的情况?也就是说:

服务器端发送了:
部门ID + 部门名称 后马上发送 用户ID + 部门ID + 用户名称

但客户端第一次收到:
部门ID + 部门名称 + 用户ID
第二次收到:
部门ID + 用户名称

会不会出现这种情况?谢谢!


netsys2 2003-04-02
  • 打赏
  • 举报
回复
TCP传输是肯定会粘包的,因此在做SERVER端时必须切割处理。

为了保证切割质量,一般每个包头都需要增加几个同步字节,SERVER根据同步字节来分割处理。

一次发一包和接收一包都是效率很低的。

我做通信很久,都是这样处理的
penu 2003-04-02
  • 打赏
  • 举报
回复
粘包是不可避免的,你的问题在接收端做下处理就好了。

1,317

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder 网络及通讯开发
社区管理员
  • 网络及通讯开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧