采用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先谢谢了,希望能够有高手能够帮助解决这个问题!
1、数据的传输频率是比较的高的,数据量大约每秒32K。
2、在Client端接收数据时,添加Sleep(5),似乎能够延长正确状态的时间。没有sleep,大约2分钟挂;有了sleep,能支持20分钟以上。
3、用了CAsyncSocketEx和CAsyncSocket都试过,没有本质区别,因为可能要支持代理,所以还是希望用CAsyncSocketEx先谢谢了,希望能够有高手能够帮助解决这个问题!
你在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,我们需要作的是,不停的接收。你出错的原因我不清楚,可以先试试我的方法。
{
// 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;
}
}
{
memcpy(&m_RecvBuf[m_RecvLen], Buf, Result);
m_RecvLen += Result;
}这一句,如果没有接受完,下次可以继续接受~没有必要加死循环的吧~否则没有接受完无法响应函数了~就变成阻塞的了~
TCP连接应该不用考虑缓冲区满的情况吧~而且跟OnReceive的不响应也没有关系~
另外看到//CAsyncSocket::OnReceive(nErrorCode);
这一行~不知道你CMySocket的基类到底是哪个~
在OnReceive里面加个断点看看能响应几次~再找原因~我是这么感觉的~
其次,这个CMySocket是继承于CAsyncSocketEx的,但是用过CAsyncSocket也是一样的现象。
再次,在客户端加sleep也不是我的本意,只是加了以后正常的状态能保持的更久罢了。如果抛开代码本身,什么情况下会出现OnReceive被阻塞呢?因为关掉服务器端后,客户端还是能够收到之前应该收到的那些数据的,所以说明这些消息并没有丢掉,只是被阻塞住了。那什么情况会造成这种阻塞呢?
我想应该不会是CAsyncSocketEx本身的问题吧,还是应该是使用上的问题吧,谁能够帮上忙,再加分!
试试CAsyncSelect(FD_READ)看能不能响应,另外还是要在OnReceive里面加个断点看看能响应几次,具体在哪一步阻塞消息了`然后找原因`
我原来也老是遇到这种问题~都是这么解决的~