CAsyncSocket的问题,急!!!

tonylk 2002-04-20 11:09:37
我做了一个基于CAsyncSocket的网络图象传输程序,在Server端,将用于数据传输的Socket设置为了阻塞模式,(Client端接收的Socket我不知道是否需要设置为阻塞模式),我将图象数据在Server端分割成大小为4380Byes的包发送,然后在Client端的OnReceive事件中接收,当我在本机地址"127.0.0.1"下调试时一切正常,可是用"192.168.0.1"(我装了网卡,这是我的网卡的静态地址,但是没有于其它及其相连)测试时,Client接收到的数据长度于我所发的数据不一致,经常是少于4380Bytes,这到底是怎么回事呢??
如果接收方会发生诸如剑法大数据分两次接收到这样的事,那我怎么才能有效的知道我接收到的数据在整个图象数据中的位置,以将它组装起来呢???
...全文
99 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
连环炮 2002-04-20
  • 打赏
  • 举报
回复
你在接收端收到的数据毫无疑问不可能是完整包,你可以自己定一个包结构,如包头,包长,消息内容等。在接收端则响应接收,如果不是完整包,则在缓冲区不处理,下一次收到的数据接在缓冲区的后面,再判断包,一直不够包长的话就一直接收,直到得到完整包。
songbird 2002-04-20
  • 打赏
  • 举报
回复
1:我不知道是否需要设置为阻塞模式
实际上,我做过类似的结构模式,两边是不是阻塞都无所谓。
据我理解,两者区别完全是本机处理请求以及相应的两种不同方式,只要使用同样的协议,就完全可以通信。
2:收到的数据少于你所期望的长度
那少的是哪儿的数据呢?尾部?
3:至于循环的依据
可以在图像数据包前面加上一个序号,比如说从1开始,每次++,发送最后一个包的时候写0。在客户端分析一下这个序号,就没有问题了。
tonylk 2002-04-20
  • 打赏
  • 举报
回复
怎么个循环法?
在发送端我却是是用循环来发的,
可是接收端,我预先并不知道图象数据的大小,循环的判断一句是什么?
huqiming 2002-04-20
  • 打赏
  • 举报
回复
做个循环接收和保存到文件
ququshb 2002-04-20
  • 打赏
  • 举报
回复
udp才会掉了
tcp不会了
ququshb 2002-04-20
  • 打赏
  • 举报
回复
2 realsong(realsong)搞什么呀???有这么复杂?
2 tonylk(tony)
int nRecvSize=0;
static STREAM_DATA JpgData;
m_pDoc->DisplayMsg("OnReceive...");
int rVal;
while(1){
rVal=Receive(&JpgData+nRecvSize,sizeof(STREAM_DATA)-nRecvSize);
nRecvSize+=rVal;
if (nRecvSize==sizeof(STREAM_DATA))
{
m_pDoc->ReceiveData(&JpgData);
break;
}
}
出错自己处理吧
tonylk 2002-04-20
  • 打赏
  • 举报
回复
我用国sleep(),虽然是可以工作,可是总是感觉不太爽。。。
后来用IOCtl()还是将它设置为阻塞模式,就好了。

现在我在client端用这样的代码来接收:
static int nRecvSize=0;
static STREAM_DATA JpgData;
m_pDoc->DisplayMsg("OnReceive...");
if (nErrorCode==0){
int rVal;
do{
rVal=Receive(&JpgData+nRecvSize,sizeof(STREAM_DATA)-nRecvSize);
if (rVal>0){
nRecvSize+=rVal;
CString sResult;
sResult.Format("Receive data size %d, total size %d.",rVal,nRecvSize);
m_pDoc->DisplayMsg(sResult);
}
else if (rVal==SOCKET_ERROR){
//int nErrCode=GetLastError();
//CString sResult;
//sResult.Format("Socket error with code %d!",nErrCode);
//m_pDoc->DisplayMsg(sResult);
nRecvSize=0;//reset this variable, even it's not correct.
}
if (nRecvSize==sizeof(STREAM_DATA)){
m_pDoc->ReceiveData(&JpgData);
nRecvSize=0;
}
}while (rVal==0);
}

可是,经常出现问题,在"if (rVal==SOCKET_ERROR){"时,当GetLastError()的错误代码为WSAEFAULT时,接收的数据大小不对,这时我设nRecvSize=0可以基本保证以后接收到的数据大小正确,可是当前这个数据包就不正确了,即丢失了一个包,我要怎样才能解决呢???
realsong 2002-04-20
  • 打赏
  • 举报
回复
tonylk (tony) :嗬嗬,碰到我算你走运,因为我遇到过这个问题:
1.默认情况下发送及接收缓冲为4k
2.由于你用的循环发送的方法,导致接收端还没来得及接收你已经发送了下一个,也就是网络带宽不够,你只要在发送端的循环语句加上 Sleep(200);试一下能不能接收到完整的数据就知道是不是这个问题了
3.改变发送的方式,也就是在确认接收端接受文政数据后向发送端反馈一个已接收的信号,发送端再发送下一个数据包(这是我采用的方式)
tonylk 2002-04-20
  • 打赏
  • 举报
回复
错了。。。
上面的代码不是会进入死循环,但是好像接收到的数据内容总是不对,

死循环的是这段:
STREAM_DATA JpgData;
int nRecvSize=0;
while (nRecvSize<sizeof(STREAM_DATA)){
int nSize=Receive(&JpgData+nRecvSize,sizeof(STREAM_DATA)-nRecvSize);
if (nSize>0){
nRecvSize+=nSize;
CString sResult;
sResult.Format("Receive data size %d.",nRecvSize);
m_pDoc->DisplayMsg(sResult);
}
}
m_pDoc->ReceiveData(&JpgData);
tonylk 2002-04-20
  • 打赏
  • 举报
回复
那我用这样的程序应该也对吧:
static int nRecvSize=0;
static STREAM_DATA JpgData;
if (nErrorCode==0){
int rVal=Receive(&JpgData,sizeof(STREAM_DATA)-nRecvSize);
if (rVal>0){
nRecvSize+=rVal;
CString sResult;
sResult.Format("Receive data size %d.",nRecvSize);
m_pDoc->DisplayMsg(sResult);
}
if (nRecvSize==sizeof(STREAM_DATA)){
m_pDoc->ReceiveData(&JpgData);
nRecvSize=0;
}
}
可是,好像会进入死循环。。。
ququshb 2002-04-20
  • 打赏
  • 举报
回复
socket是做为流式数据发送和接收的,也就是说它只保证按序列正确发送数据,但是它没保证发送长度和接收长度符合 例如:
发送为2个包
第一个包数据: abcde
第二个包数据: fgh
但接收时,receive 少于发送长度
例如 : 第一次receive的数据:abc
第二次receive 的数据: de
。。。。
所以,你要自己保证接收长度,
也就是做个循环,和数据结构:
struct data{
int length;
char buffer[size]
}

接收时
data mydata;
char *p = &mydata;
int len = recievie (p,sizeof(data));
while (len < sizeof(data))
{
receive (p + len,sizeof(data) - len));
// 循环接收直到sizeof(data)
}
搞定
qiuanhong 2002-04-20
  • 打赏
  • 举报
回复
UP
tonylk 2002-04-20
  • 打赏
  • 举报
回复
我的包结构是:
#define PackageSize 4368
typedef struct _STREAM_DATA{
int nIndex;//包序号
BOOL bEnd;//是否最后一个包
DWORD nSize;//本包有效数据的长度
BYTE Buffer[PackageSize];//具体数据
}STREAM_DATA;

我在每次OnReceive时这样处理:
void CClientStreamSocket::OnReceive(int nErrorCode)
{
STREAM_DATA JpgData;
int nRecvSize=Receive(&JpgData,sizeof(STREAM_DATA));
if (nRecvSize==sizeof(STREAM_DATA)){
m_pDoc->ReceiveData(&JpgData);//我在Doc中处理具体的数据保存工作
}
else{
CString sResult;
sResult.Format("Receive data size not correct %d.",nRecvSize);
m_pDoc->DisplayMsg(sResult);
}
CAsyncSocket::OnReceive(nErrorCode);
}

在局域网时不会出现"Receive data size not correct..."的提示,可是广域网时就经常出问题。。。。

16,473

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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