[期待高手]CAsyncSocketEx(CAsyncSocket)消息被阻塞的问题

hfkobe 2006-08-28 02:33:35
采用CAsyncSocketEx进行客户端\服务器socket通讯,期初一切正常,但是通讯一段时间后,Client端无法再收到数据(OnReceive)没有被触发,但是Server还是一直在发送数据,且Send的返回值没有异常,之后就一直保持这种Server发送成功,但Client无法接收的状态。这时如果关闭Server端程序,Client会触发OnReceive,并且能够收到之前应该收到的数据,最后触发OnClose。

辅助信息:
1、数据的传输频率是比较的高的,数据量大约每秒32K。
2、在Client端接收数据时,添加Sleep(5),似乎能够延长正确状态的时间。没有sleep,大约2分钟挂;有了sleep,能支持20分钟以上。
3、用了CAsyncSocketEx和CAsyncSocket都试过,没有本质区别,因为可能要支持代理,所以还是希望用CAsyncSocketEx

先谢谢了,希望能够有高手能够帮助解决这个问题!
...全文
637 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
xb_luotuo 2006-11-05
  • 打赏
  • 举报
回复
这个问题的确存在,我在开发大文件传输的过程中,就遇到这个问题。经过试验,发现是CAsyncSocket性能的问题,如果没有好办法就只有自己封装SOCKET了,期待大家有什么简洁的办法可以解决这个问题!
islife 2006-10-03
  • 打赏
  • 举报
回复
我也遇到这种问题,不响应ONRECEIVE消息,后来换个网络和几台机器,居然好了
toxyboy 2006-09-06
  • 打赏
  • 举报
回复
楼主怎么样了???解决没,说说结果撒。。
楼上你没碰到过这样的问题,当然会出鬼了。
ludismd 2006-09-02
  • 打赏
  • 举报
回复
每次系统调用onreceive,你只要确保能把缓冲区数据都读完,就不会有问题。在Onreceive里啥也别干,就do {int Ret = Receive(buf,size) TRACE("");}while(ret == size)。

如果运行仍不正常,那就出鬼了!
yebeans 2006-08-30
  • 打赏
  • 举报
回复
这上面只能讨论讨论原理性的东西~具体的话不调试也不好说~你贴出来的代码除了for这一句(接受数据没有错~,只是完全没有必要,而且怀疑它会阻塞消息)~都跟例程格式差不多~也看不出来什么~
试试CAsyncSelect(FD_READ)看能不能响应,另外还是要在OnReceive里面加个断点看看能响应几次,具体在哪一步阻塞消息了`然后找原因`
我原来也老是遇到这种问题~都是这么解决的~
CW_Wei 2006-08-30
  • 打赏
  • 举报
回复

hfkobe 2006-08-30
  • 打赏
  • 举报
回复
希望大家一定帮帮忙啊
现在就卡在这个问题上面了,郁闷啊
toxyboy 2006-08-30
  • 打赏
  • 举报
回复
异步socket是基于消息驱动的,按说不进入死循环,不需要显式的指定AsyncSelect,就因该可以触发On事件,但是我也遇到过几次On事件不能触发的问题,后来每次Send或者Recv事件之后都加了一个AsyncSelect效果好很多,没有大数据量的测试,基本在没有出现过消息不能触发的问题。还有就是所有的事件处理要在开Socket的线程内运行,跨线程消息传递不过去。
toxyboy 2006-08-30
  • 打赏
  • 举报
回复
在任何调用On事件的函数体里面加一个AsyncSelect。。。。和Sleep没有关系的,Sleep是把整个线程挂起。这个问题,我也碰到过,纳闷ing!
hfkobe 2006-08-29
  • 打赏
  • 举报
回复
首先,出现异常情况的时候,客户端程序并没有停止响应,也就是说没有阻塞。
其次,这个CMySocket是继承于CAsyncSocketEx的,但是用过CAsyncSocket也是一样的现象。
再次,在客户端加sleep也不是我的本意,只是加了以后正常的状态能保持的更久罢了。

如果抛开代码本身,什么情况下会出现OnReceive被阻塞呢?因为关掉服务器端后,客户端还是能够收到之前应该收到的那些数据的,所以说明这些消息并没有丢掉,只是被阻塞住了。那什么情况会造成这种阻塞呢?
yebeans 2006-08-29
  • 打赏
  • 举报
回复
有if(m_RecvLen + Result < m_RecvMaxLen)
{
memcpy(&m_RecvBuf[m_RecvLen], Buf, Result);
m_RecvLen += Result;
}这一句,如果没有接受完,下次可以继续接受~没有必要加死循环的吧~否则没有接受完无法响应函数了~就变成阻塞的了~
TCP连接应该不用考虑缓冲区满的情况吧~而且跟OnReceive的不响应也没有关系~
另外看到//CAsyncSocket::OnReceive(nErrorCode);
这一行~不知道你CMySocket的基类到底是哪个~
在OnReceive里面加个断点看看能响应几次~再找原因~

我是这么感觉的~
Elysium 2006-08-29
  • 打赏
  • 举报
回复
我觉得最好放到一个单独的线程里处理,sleep会造成用户界面无响应,而且数据量不小,时间长了,数据处理不过来,就会造成一直在接收数据,无法处理的情况,缓冲区也会满掉,而且客户端sleep虽然可以保证开始的数据处理准确,但是服务端的源源不断的数据进来最后也会把链路堵死,服务器可以加一个更长的sleep,或者将客户端的数据处理单独剥离出来
cloudgamer 2006-08-29
  • 打赏
  • 举报
回复
循环直到读完吧
hfkobe 2006-08-29
  • 打赏
  • 举报
回复
现在我改用了SOCKET,接收数据这块代码没做任何的改变,没有再出现问题了。
我想应该不会是CAsyncSocketEx本身的问题吧,还是应该是使用上的问题吧,谁能够帮上忙,再加分!
yebeans 2006-08-28
  • 打赏
  • 举报
回复
ReadData(void)里面为什么要加死循环?
hfkobe 2006-08-28
  • 打赏
  • 举报
回复
希望能够得到大家的点拨
hfkobe 2006-08-28
  • 打赏
  • 举报
回复
void CMySocket::OnReceive(int nErrorCode)
{
// TODO: Add your specialized code here and/or call the base class
ReadData();
if(m_pClient) m_pClient->OnReceive(nErrorCode);
CAsyncSocketEx::OnReceive(nErrorCode);
// CAsyncSocket::OnReceive(nErrorCode);
}

void CMySocket::ReadData(void)
{
int Result;
char Buf[1024];
char * NewBuf;

for(;;)
{
Result = Receive(Buf, sizeof(Buf));

if(Result == 0)
{
m_Connected = false;
Close();
return;
}
if(Result == SOCKET_ERROR)
{
switch(GetLastError())
{
case WSAEMSGSIZE:
//MessageBox(NULL, "The message was too large to fit into the specified buffer and was truncated.", "", MB_OK);
break;

case WSAENETRESET:
case WSAECONNABORTED:
case WSAETIMEDOUT:
case WSAECONNRESET:
m_Connected = false;
Close();
return;
}
break;
}

if(m_RecvLen + Result < m_RecvMaxLen)
{
memcpy(&m_RecvBuf[m_RecvLen], Buf, Result);
m_RecvLen += Result;
}else{
// NewBuf = new char [m_RecvLen + Result];
NewBuf = MAlloc(char, m_RecvLen + Result);

memcpy(NewBuf, m_RecvBuf, m_RecvLen);
memcpy(&NewBuf[m_RecvLen], Buf, Result);

MFree(m_RecvBuf);
m_RecvBuf = NewBuf;

m_RecvLen += Result;
m_RecvMaxLen = m_RecvLen;
}
m_RecvBytes += Result;
}
}
DentistryDoctor 2006-08-28
  • 打赏
  • 举报
回复
不清楚你代码是怎么写的。
sea_zs 2006-08-28
  • 打赏
  • 举报
回复

你在OnReceive里是怎么接收数据的?
一次全部接收吗?

我用的是CAsyncSocket类,在接收信息方面与CAsyncSocketEx不会有差别,下面是我接收数据的方法,不是一次接收,分包接收,不需要Sleep,请参考:

char buf[10240];
ZeroMemory(buf, 10240);
CString str;
CString sMessage;

int nRead = Receive(buf, 10240);
switch (nRead)
{
case 0:
Close();
break;

case SOCKET_ERROR:
if (GetLastError() != WSAEWOULDBLOCK)
{
AfxMessageBox ("Error occurred");
Close();
}
break;

//receive message successfully
default:
buf[nRead] = 0;
sMessage = buf;

.......

.......

str += sMessage;
m_pAsyncSocketClientDlg->ShowMessage(str);
}
CAsyncSocket::OnReceive(nErrorCode);

处理过程可能有不经典的地方,但原理是标准的,因为接收数据的时候都应该一部分一部分的接收,在缓存区中,只要有数据,就会不停的触发OnRecive,我们需要作的是,不停的接收。

你出错的原因我不清楚,可以先试试我的方法。

18,356

社区成员

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

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