接收数据时,CAsyncSocket的异步非阻塞与CSocket的同步阻塞 的特点。

Luo_Bryant 2013-05-29 12:45:43
下面是ftp客户端接收服务器数据的一个函数。

BOOL CFTPclient::MoveFile(CString RemoteFile , CString LocalFile , BOOL pasv , BOOL get)
{
CString lhost,temp,rhost;
UINT localsock,serversock,i,j;
CFile datafile;
CSocket sockSrvr;
CAsyncSocket datachannel;
int num,numread,numsent;
const int BUFSIZE=4096;
char cbuf[BUFSIZE];
DWORD lpArgument=0;

// 打开本地文件
if(!datafile.Open(LocalFile,CFile::modeWrite|CFile::modeCreate))
{
return FALSE;
}
if(!FTPcommand("TYPE I")) return FALSE; // 请求二进制传输
// 设置主动的传输模式
//获取本地的ip地址,发送到服务器
if(!m_pCtrlSock->GetSockName(lhost,localsock)) return FALSE;
while(1)
{ // 将IP地址中的点转化成逗号
if((i=lhost.Find("."))==-1) break;
lhost.SetAt(i,',');
}
// 创建数据传输socket并侦听
if((!sockSrvr.Create(0,SOCK_STREAM,NULL))||(!sockSrvr.Listen())) return FALSE;
if(!sockSrvr.GetSockName(temp,localsock)) return FALSE;// get the port that MFC chose
// 将端口转化成2字节,然后加入到本地IP地址中
lhost.Format(lhost+",%d,%d",localsock/256,localsock%256);
if(!FTPcommand("PORT "+lhost)) return FALSE;// 发送端口到服务器

// 发送 RETR 命令到服务器
if(!WriteStr(("RETR ")+RemoteFile)) return FALSE;

if(!ReadStr()||m_fc!=1) return FALSE; // 获得服务器响应

if(!sockSrvr.Accept(datachannel)) return FALSE; // 接收从服务器来的内部绑定数据



/*
// 连接成功,然后进行同步阻塞式数据传输
if( (!datachannel.AsyncSelect(0)) || (!datachannel.IOCtl(FIONBIO,&lpArgument)) )
{
return FALSE;
}

*/


CString str;
while(1)
{
// 开始传输数据
if( !(num=datachannel.Receive(cbuf,BUFSIZE,0)) || num == SOCKET_ERROR )
{
int err = GetLastError();
str.Format("%d\n" , err);
AfxMessageBox(str);
break; // (EOF||network error)
}
else
datafile.Write(cbuf,num); //将数据写入文件
}
datachannel.Close();
datafile.Close();
if(!FTPcommand(""))
return FALSE; // 检查服务返回的响应
return TRUE; // 传输成功
}



问题:

1、将CAsyncSocket datachannel设置为同步阻塞模式去接收数据,几十 M 的文件都可以接收得到,可是当我不把CAsyncSocket datachannel设置为同步阻塞(如以上代码)的情况下去接收数据,最多只能接收66KB的文件 ,大于66KB的文件就不能接收了,这是为什么呀???

2、不把CAsyncSocket datachannel设置为同步阻塞去接收数据,然后我加断点一步一步调试,这时候却能接收得到几十 M 的文件哦。。。
...全文
128 6 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
Luo_Bryant 2013-05-29
  • 打赏
  • 举报
回复
引用 1 楼 zhoujielunzhimi 的回复:
CAsyncSocket datachannel; 换成 CSocket datachannel; 或者 if( !(num=datachannel.Receive(cbuf,BUFSIZE,0)) || num == SOCKET_ERROR ) 修改这个判断,容我查查资料
第二个问题,不把CAsyncSocket datachannel设置为同步阻塞去接收数据(CAsyncSocket datachannel还是异步阻塞),然后加断点一步一步调试,这时候却能接收得到几十 M 的文件哦。。。 为什么调试了,最后就能接收到几十M 的文件的呢?
Luo_Bryant 2013-05-29
  • 打赏
  • 举报
回复
引用 1 楼 zhoujielunzhimi 的回复:
CAsyncSocket datachannel; 换成 CSocket datachannel; 或者 if( !(num=datachannel.Receive(cbuf,BUFSIZE,0)) || num == SOCKET_ERROR ) 修改这个判断,容我查查资料
呵呵,第一个问题已解决。 CAsyncSocket datachannel; 换成 CSocket datachannel; 或者: CAsyncSocket datachannel 是异步非阻塞的 这么修改好了
		if(!(num = datachannel.Receive(cbuf , BUFSIZE)))
			break;
		else if(num == SOCKET_ERROR)
		{
			int err = GetLastError();
		    if(err == WSAEWOULDBLOCK)
			{
			    continue;
			}
		
		}
		else
			datafile.Write(cbuf , num);
那第二个问题呢?
sumos 2013-05-29
  • 打赏
  • 举报
回复
CAsyncSocket datachannel; 换成 CSocket datachannel; 或者 if( !(num=datachannel.Receive(cbuf,BUFSIZE,0)) || num == SOCKET_ERROR ) 修改这个判断,容我查查资料
Eleven 2013-05-29
  • 打赏
  • 举报
回复
异步模式下,函数返回失败的情况下,调用WSAGetLastError() == WSA_IO_PENDING,如果是的话,不表示出错,否则出错了。
youngwolf 2013-05-29
  • 打赏
  • 举报
回复
异步读,当返回SOCKET_ERROR的时候,不一定是出错,要根据WSAGetLastError返回值来决定,你不看msdn啊。 你调试状态下,影响了接收速度,相当于接收慢了,那么极有可能每次都能收到数据,那么就有可能正确的接收完所有数据。非调试状态下,接收速度非常快,极有可能出现没有数据可接收的状态(但数据还没发完),此时你的代码就break了。
sumos 2013-05-29
  • 打赏
  • 举报
回复
char buf[1024]; while(true) { int n = sk.Receive(buf, sizeof(buf), 0); if(n == 0) // 无数据 break; else if(n > 0) f.Write(buf, n); else { int e = WSAGetLastError(); if(e == WSAEWOULDBLOCK) continue; //数据还未接收完 else { MessageBox("Receive error"); break; } } }

18,363

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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