加载中…
个人资料
南冠彤
南冠彤
  • 博客等级:
  • 博客积分:0
  • 博客访问:414,747
  • 关注人气:59
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
相关博文
推荐博文
谁看过这篇博文
加载中…
正文 字体大小:

(转)关于UDP socket 的10054错误解决办法

(2012-06-26 10:56:51)
标签:

杂谈

分类: CPP/C
http://blog.csdn.net/ccnucjp8136/article/details/4515002

今天碰到了一个非常怪的问题,我的主要功能是先用UDP的Sendto发送一个数据过去,同时启动一个线程,这个线程去recvfrom来自远目地主机的包,但是每次我Sendto后,recvfrom不阻塞在那里,而报10054的错误。先贴代码

第一部分:主要是初始化

 WSADATA wsaData;
 WSAStartup(MAKEWORD(2,2), &wsaData);

   

 m_nPort = GetConfigValue("BIPSERVERCONFIG", "CATPORT", 8888);//获取服务目的端口
 m_ServerAdd = GetConfigValue("BIPSERVERCONFIG" ,"CATADDRESS", "127.0.0.1");//获取服务目的端口

    m_ServerAddress.sin_family = AF_INET;
 m_ServerAddress.sin_port   = htons(m_nPort);
 m_ServerAddress.sin_addr.s_addr = inet_addr(m_ServerAdd);
 //m_ServerAddress.sin_addr.s_addr = inet_addr("10.8.4.52");

 
 m_ClientAddress.sin_family = AF_INET;
 m_ClientAddress.sin_port   = htons(0);
 m_ClientAddress.sin_addr.s_addr = htons(INADDR_ANY);

 m_ClientSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
 if(m_ClientSocket == SOCKET_ERROR)
 {
  DWORD dwError = GetLastError();
  TRACE("错误码:%d", dwError);
  WriteRunLog_EX("InitSocket","初始化套接字错误/n");
  return FALSE;
 }


 
    int ret = 0;
 ret = bind(m_ClientSocket, (struct sockaddr*)&m_ClientAddress, sizeof(m_ClientAddress));
 if (ret != 0)
    
  DWORD dwError = GetLastError();
  TRACE("错误码:%d", dwError);
  WriteRunLog_EX("InitSocket","bind套接字错误/n");
  return FALSE;
    }

 

第二部分:Sendto处代码:从这里你可以看到,我Sendto一个包给远端目的主机马上启动一个线程去收数据。

 retCode = sendto(m_ClientSocket, lpBuf,len, 0,(struct sockaddr*)&m_ServerAddress, sizeof(m_ServerAddress));
    if (SOCKET_ERROR == retCode)
    {
  return FALSE;
    }

 ///int addressLen = sizeof(addr);
 //retCode = recvfrom(m_ClientSocket, lpBuf, len, 0, (struct sockaddr*)&addr, &addressLen );

 
 pRecvThread = AfxBeginThread((AFX_THREADPROC)StartRecvProc,this,THREAD_PRIORITY_NORMAL);
 if (NULL == pRecvThread)
  
  TRACE("启动接收线程失败!");
  WriteRunLog_EX("StartRecv","bind错误/n");
  return FALSE;

 }

 

第三部分:收线程的代码

while (TRUE)
 {
  int addressLen = sizeof(struct sockaddr);
  retCode = recvfrom(m_ClientSocket, data, sizeof(data), 0, (struct sockaddr*)&m_ServerAddress, &addressLen );
  if (SOCKET_ERROR == retCode)
  {
   DWORD dwError = GetLastError();
   TRACE("错误码为:%d",dwError);
   
   TRACE("收包错误!");
            WriteRunLog_EX("StartRecv","收包错误/n");
  }
  else
  {
   char testBuf[8192];
   memcpy(testBuf, data, retCode);
   testBuf[retCode] = '/0';
   TRACE("StartRecv收到包:%s",testBuf);
   BIP_CATMsg msg;
   msg.len = retCode;
   memcpy(msg.strBuf, data, msg.len);
   m_RecvMsgQueue.AddTail(msg);
  }
   
 

我的本意在这个recvfrom处应会阻塞,但是没有,GetLastErrorr后显示10054,我在网上查了一下,原来是winsock自已的bug。具体原因是:http://support.microsoft.com/kb/263823/

If sending a datagram using the sendto function results in an "ICMP port unreachable" response and the select function is set for readfds, the program returns 1 and the subsequent call to the recvfrom function does not work with a WSAECONNRESET (10054) error response. In Microsoft Windows NT 4.0, this situation causes the select function to block or time out.

解决办法:在我第一部代码初始化后加入如下代码。

 DWORD dwBytesReturned = 0;
 BOOL bNewBehavior = FALSE;
 DWORD status;

#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
 // disable  new behavior using
 // IOCTL: SIO_UDP_CONNRESET
 status = WSAIoctl(m_ClientSocket, SIO_UDP_CONNRESET,
  &bNewBehavior, sizeof(bNewBehavior),
  NULL, 0, &dwBytesReturned,
  NULL, NULL);

 if (SOCKET_ERROR == status)
 {
  DWORD dwErr = WSAGetLastError();
  if (WSAEWOULDBLOCK == dwErr)
  {
   // nothing to do
   return(FALSE);
  }
  else
  {
   printf("WSAIoctl(SIO_UDP_CONNRESET) Error: %d/n", dwErr);
   return(FALSE);
  }
 }

真是受教了,这个问题调了我好久。


0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4000520066 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有