网络编程里的组包问题(粘包)求组。

hanzitao1979 2010-06-15 05:52:30
以ClientSocket SendBuf模式发送和接收数据,发送结构体,接收的时候也读入结构体,这样封包比较清晰

定义包结构体
typedef struct PKHead
{
DWORD PackId; //包类型
DWORD PackDateLen; //包数据长度
//包实际数据
}PKHead;
typedef struct Pack
{
PKHead pHead;
char *pDate; // 传送的数据
}Pack;

char m_pBuff[1024]; //定义接收包缓存
int m_Pbuffsz=sizeof(m_pBuff); //数组定义长度
int m_Pbuffst=StrLen(m_pBuff); //数组实际内容长度

/*****************************************************************************
服务端发送一个包过来首先判断是否缓存能够装下?装的下装入,装不下扩充缓存。
但是存在一些问题。比如我发送结构体过来的时候可能是1234\0\0\0 但是扩充代码会造成\0\0消失,当我用结构体去读入数据的时候就乱了。

Description:添加数据到缓存的函数
Input:pBuff[in]-待添加的数据;nLen[in]-待添加数据长度
******************************************************************************/
BOOL __fastcall TForm1::AddBuff( char *pBuff, int nLen )
{

if ( nLen <= m_Pbuffsz-m_Pbuffst)///判断剩余空间是否足够存放nLen长的数据,这个地方就有问题假设缓存里已经存在123\0\0456这个数据,通过strlen方式那么只得到长度为3;而实际长度是8,因为遇见了\0;
{
StrCat(m_pBuff, pBuff );
m_Pbuffst += nLen;
}
else///若不够则扩充原有的空间
{
char *p = m_pBuff ;//每次增长2*nLen //这里也是本来是123\0\0\0的话 p就只有123了

char * m_pBuff = new char[m_Pbuffsz];
memcpy(m_pBuff,p,m_Pbuffst);
delete []p;
StrCat(m_pBuff , pBuff);
m_Pbuffst += nLen;
//m_cs.Unlock();
return TRUE;
}
//m_cs.Unlock();
return TRUE;
}

以上代码存在很多问题,只是一个思路。请各位高手能给个代码学习下。原理我也知道。参考了网上有人写的代码也有问题比如http://www.cnblogs.com/yjmyzz/archive/2009/12/01/1614326.html 不知如何能满足我结构体整体的发送和接收,处理定长时候数据位不满\0问题

本人初学socket编程。还望大家多指导啊,最好能给出详细的代码针对组包和读取 谢谢啊。端午快乐

...全文
295 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhujuncug 2010-07-04
  • 打赏
  • 举报
回复
在应用层次定协议,来解决粘包的问题
BCBNJHOME 2010-07-02
  • 打赏
  • 举报
回复
CppFile 兄弟能不能给出一个演示的c /s 的收包处理代码。
hanzitao1979 2010-06-17
  • 打赏
  • 举报
回复
CppFile 兄弟能不能给出一个演示的c /s 的收包处理代码。或者能不能留个qq号码我加你
CppFile 2010-06-16
  • 打赏
  • 举报
回复
不用用strcat来复制数据,因为不是字符串处理, 可以用memcpy来复制内存数据,这样\0这样的数据就可以复制过来了

在处理内存中数据的时候,不能使用字符串处理函数,因为你不知道什么时候碰到\0,及有可能造成缓冲区溢出。

另外,结构中使用char *指针,我觉得不太妥当,最好是固定长度char data[size]这样的,size取数据包的最大数值,发送的时候,只需把有数据的部分发出即可,比如char data[256],实际包中的数据只有128个,只需要socket->sendbuffer(...,128)即可
周药师 2010-06-16
  • 打赏
  • 举报
回复
\Borland\Examples\Internet\Chat
C++Builder 安装目录下的例子,自己去看看吧
周药师 2010-06-16
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 hanzitao1979 的回复:]
大哥\Borland\Examples\Internet\Chat
C++Builder 安装目录下的例子,自己去看看吧
这个歌垃圾代码直接都把这种粘包情况忽略了。根本就不处理。。。。实际上那个chat源码是有问题的
[/Quote]
你在3楼不是要一个传输的列子吗?

你要解决粘包的问题,根本的还是你要去定协议
记住:虽然是粘包,但绝不会改变包的发送顺序
所以你定义好协议后,
接收端无论一起收,还是分开收,你接收的时候根据协议去收,根据协议判断是否收完;
收完后你把收到的数据按照你的协议去分解,然后得到你需要的数据去做业务处理,
这样子就不会出什么问题
hanzitao1979 2010-06-16
  • 打赏
  • 举报
回复
大哥\Borland\Examples\Internet\Chat
C++Builder 安装目录下的例子,自己去看看吧
这个歌垃圾代码直接都把这种粘包情况忽略了。根本就不处理。。。。实际上那个chat源码是有问题的
hanzitao1979 2010-06-15
  • 打赏
  • 举报
回复
你好楼上的朋友。另外如何用byte去传输了?能否写个完整的代码我好学习下啊
周药师 2010-06-15
  • 打赏
  • 举报
回复
“服务端发送一个包过来首先判断是否缓存能够装下?装的下装入,装不下扩充缓存。”
发送的时候控制好发送的长度,定好协议
接收端根据协议来接收数据,处理数据,
不要发送随意长度的数据
周药师 2010-06-15
  • 打赏
  • 举报
回复
"如我发送结构体过来的时候可能是1234\0\0\0 但是扩充代码会造成\0\0消失,"
这是因为你用的char类型 char碰到'\0'就结束了

你可以用byte去传输

1,317

社区成员

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

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