VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

有编程疑问吗?还请到提问专区发帖提问!
搜索
查看: 490|回复: 2

[求助] CAsyncSocket类OnReceive接收数据

[复制链接]
80_avatar_middle
在线会员 chengf 发表于 2017-8-17 22:50:23 | 显示全部楼层 |阅读模式
3驿站币
提问:OnReceive 如何接受一个完整的数据包?
现接收的数据包格式如下:
struct _senddata_
{
int msgid;//消息ID
size_t datasize;
char *buff;
};
发送时,这个数据包是被压到一个 char *sendbuff; 中的,接受这个数据要先从sendbuff中取出msgid和datasize,然后再根据datasize接受数据。

CAsyncSocket类的OnReceive是基于消息机制的,由于不太了解CAsyncSocket类,所以不知道如何完整接受这个数据包,并且不会出现断包,连包等情况。

我的解决办法如下(这个解决办法有问题):
  1. void CServerappDlg::OnReceive(CMySocket *asyncSocket)
  2. {
  3.         char str[50]={0};//接受数据头数据的buff
  4.        
  5.         static size_t datalen=0;//已读取的数据长度
  6.         static char *buff=NULL;//保存接收的数据包buff
  7.         static int msgid;//数据包的消息ID,用于识别数据消息类型
  8.         static size_t datasize;//数据包的长度
  9.         int ret;

  10.         do
  11.         {
  12.                 if (buff == NULL)
  13.                 {//数据头
  14.                         ret = asyncSocket->Receive(str,sizeof(msgid)+sizeof(datasize));
  15.                        
  16.                         if (ret >= 0)
  17.                         {
  18.                                 memcpy(&msgid,str,sizeof(msgid));
  19.                                 memcpy(&datasize,str+sizeof(msgid),sizeof(datasize));
  20.                                 if (datasize == 0)//只有消息ID的数据包
  21.                                 {
  22.                                         DealWithMsgData(asyncSocket,msgid,buff,datasize);
  23.                                         break;
  24.                                 }
  25.                                 buff = (char*)malloc(datasize);//申请空间
  26.                                 datalen = 0;
  27.                         }
  28.                 }
  29.                 else
  30.                 {//数据buff
  31.                         ret = asyncSocket->Receive(buff+datalen,datasize-datalen);
  32.                         if (ret > 0)
  33.                         {
  34.                                 if (datalen+ret >= datasize)//数据包读取完成
  35.                                 {
  36.                                         //处理包数据
  37.                                         //msgid是包消息类型 datasize 是数据包大小 buff是数据包内容
  38.                                         OutputDebugString(buff);
  39.                                         DealWithMsgData(asyncSocket,msgid,buff,datasize);//处理接收数据的函数,这个可以自己定义
  40.                                        
  41.                                         //释放包数据
  42.                                         free(buff);
  43.                                         datasize=0;
  44.                                         datalen=0;
  45.                                         buff = NULL;
  46.                                         break;
  47.                                 }
  48.                                 else
  49.                                 {
  50.                                         datalen += ret;
  51.                                 }
  52.                         }
  53.                         else
  54.                         {//出现错误?
  55.                                 int error;
  56.                                 error = asyncSocket->GetLastError();
  57.                                 char str[260];
  58.                                 wsprintf(str,"服务端错误代码:%d",error);
  59.                                 MessageBox("接收失败!",str);
  60.                                 SetLastError(0);
  61.                                 break;
  62.                         }
  63.                 }
  64.         }while(ret > 0);

  65. }
复制代码

这个解决办法一开始还可以用,但是接收几十个数据包后就出现异常,CAsyncSocket类的OnReceive就无法接收到数据了
所以在这里请教各位大神!麻烦帮我看看,哪里出现问题了?感谢!!!





上一篇:C 语言window编程结构体问题
下一篇:visual c++ 怎样把代码生成一个exe程序

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

80_avatar_middle
ico_lz  楼主| chengf 发表于 2017-8-17 22:51:31 | 显示全部楼层
  1. int CMySocket::SendData(int msgid,char *buff, size_t buffsize)//参数分别是消息ID,发送的数据,发送数据的大小
  2. {
  3.         char *sendbuff=NULL;
  4.         int ret=0,count=0;
  5.         sendbuff = (char*)malloc(buffsize+sizeof(msgid)+sizeof(buffsize));
  6.         memcpy(sendbuff,&msgid,sizeof(msgid));
  7.         memcpy(sendbuff+sizeof(msgid),&buffsize,sizeof(buffsize));
  8.         memcpy(sendbuff+sizeof(msgid)+sizeof(buffsize),buff,buffsize);

  9. //以下是发送的主要代码---------------------------------------------------------------------------
  10.         ret = Send(sendbuff,buffsize+sizeof(buffsize)+sizeof(msgid));

  11.         int sendsize = buffsize+sizeof(buffsize)+sizeof(msgid);
  12.         for (int sendpos=ret; sendpos < sendsize; sendpos += ret)
  13.         {
  14.                 ret = Send(sendbuff+sendpos,sendsize-sendpos);
  15.                 Sleep(1);
  16.         }
  17.         free(sendbuff);//释放buff
  18. //----------------------------------------------------------------------------------------------------------
  19.         return ret;
  20. }
复制代码



这个是发送的代码,也贴上来。

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复

使用道具 举报

51_avatar_middle
online_admins Syc 发表于 2017-8-17 23:34:37 | 显示全部楼层
你这个粘包的处理写的不太好。
你应该是先调用 asyncSocket->Receive 一下,楼主代码中给的第一次接收的大小是:sizeof(msgid)+sizeof(datasize) 也就是包头的长度,那么接收完了之后应该判断 ret 的长度,跟包头的长度做对比,看看一个完整的包头是否接收完整,而不是单纯的判断 ret >= 0,如果接收的长度小于包头的长度,那么把接收到的数据直接 push 到一个缓冲区中,如果接收的长度大于等于包头的长度,接着就判断包体的长度是否接收完整了,如果包体的长度不够,那么把之前接收的数据接着push到缓冲区中,之后继续接收包体,知道包体接收完整,这个数据包就算是完整了,拿过去处理就行了。接着再接收第二个包的包头,以此类推!

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

关闭

站长提醒上一条 /1 下一条

QQ
QQ在线咨询
联系电话
13591366679
手机扫一扫 关注本站精彩内容
wxqrcode

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号tongdun|网站地图wx_jqr

GMT+8, 2018-10-20 15:40

Powered by Discuz! X3.4

© 2009-2018 cctry.com

快速回复 返回顶部 返回列表