Winsock UDP编程中,大家怎么处理ICMP错误?

zengkun100 2007-07-18 12:09:01
情况如下:
有个echo的UDP服务器,它收到客户端发来的数据后再原封不动地发回给客户端。代码片段大致如下:
while(true)
{
nAddrLen = sizeof(SOCKADDR_STORAGE);
if((nRecvdBytes = recvfrom(ReceivingSocket, szRecvBuf, 256, 0, (sockaddr*)&SenderAddr, &nAddrLen)) == SOCKET_ERROR)
{
cout<<"ERROR: recvfrom failed with error: "<<WSAGetLastError()<<endl;
closesocket(ReceivingSocket);
WSACleanup();
break;
}

Ret = sendto(ReceivingSocket, szRecvBuf, nRecvdBytes, 0, (SOCKADDR *)&SenderAddr, nAddrLen);
if(SOCKET_ERROR == Ret)
{
cout<<"ERROR: sendto failed with error: "<<WSAGetLastError()<<endl;
closesocket(ReceivingSocket);
WSACleanup();
break;
}
}
现在的问题是:当UDP服务器接收到数据之后,在它把数据发送给客户端之前,客户端关闭了,这时发送就会导致一个ICMP端口不可达的错误。当然,那个sendto操作还是会成功的,只是下一次的recvfrom操作就会出错,返回的错误代码是WSAECONNRESET,MSDN上是这样解释的:
On a UDP-datagram socket this error indicates a previous send operation resulted in an ICMP Port Unreachable message.

为了不让这个recvfrom操作出错,我是这样解决的:
在创建了这个UDP的服务器端socket之后,就给它的I/O设置了个属性
BOOL bConnReset = FALSE;
DWORD dwBytesReturned = 0;
WSAIoctl(ReceivingSocket, SIO_UDP_CONNRESET, (void*)&bConnReset, sizeof(BOOL), (void*)&Ret, sizeof(int), &dwBytesReturned, 0 ,0);

想问问各位,你们是怎么处理Winsock编程中的UDP错误的?
...全文
526 5 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
zengkun100 2007-07-23
  • 打赏
  • 举报
回复
OK了,去Google了一把,看到别人也是这么解决的。
开来以后有什么问题还是应该先Google一下,不要动辄就上论坛啊!
partime 2007-07-19
  • 打赏
  • 举报
回复
我从来是通过select来处理
不会有recvfrom发生错误的情况
在网络底层出错时recvfrom接收0字节
zengkun100 2007-07-19
  • 打赏
  • 举报
回复
我的意思是:sendto能否成功是无所谓的,但是问题是sendto之后,再掉recvfrom就会出错。也就是说UDP服务器在发生一个sendto错误后就没办法继续接收其他UDP客户端发来的数据了,这当然不是我想要的结果。

为了解决这个问题,我在创建socket后调用了WSAIoctl函数修改了socket的属性。recvfrom就可以继续接收数据。

我是想问:有没有人遇到过类似的问题,你们是怎么处理的?

To:xujianlane(头文字C)。sendto为什么会成功呢?对于sendto产生的WSAECONNRESET错误,MSDN上是这么说的:For UPD sockets, the remote host was unable to deliver a previously sent UDP datagram and responded with a "Port Unreachable" ICMP packet. The application should close the socket as it is no longer usable.
的确,第一次的send是会成功的(事实上对方其实根本没有收到这个UDP包),但是它已经导致了一个ICMP端口不可达错误的产生,因此接下来在这个socket上调用recvfrom会出错。如果这个时候再调一次sendto,就会得到一个WSAECONNRESET错误了。

To:partime(partime)。你似乎没有明白我说的是什么,不过还是谢谢你顶帖。
xujianlane 2007-07-18
  • 打赏
  • 举报
回复
>>那个sendto操作还是会成功的
为什么会成功啊?应该也是WSAECONNRESET
partime 2007-07-18
  • 打赏
  • 举报
回复
UDP....
如果你需要处理错误,可能就不该用UDP

最简单就是保留你要发送的数据,以后再重试了
还能怎么处理
怎么处理与你要发的东西有关啊
你无所谓的东西扔掉就不管好了

18,363

社区成员

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

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