C ++ UDP sendto失败,需要睡眠

时间:2014-05-26 17:09:00

标签: c++ udp sendto

我有一个UDP客户端C ++代码 - 基于WSA套接字 - 运行良好。该代码最初是用VS6编写的,我最近在VS2010中为64位环境重新编译了它,只做了很少的调整。

现在,如果在sendto()之后和closesocket()之前没有Sleep(..)或任何等效延迟,则sendto()无法发送内容。 “失败”意味着,sendto()返回适当数量的数据,但我看不到网络上的消息(我使用wireshark来检查这个)。

这是我的代码:

void CTest::SendHello()
{
  SOCKET sSocket;
  sSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

  struct sockaddr_in addr;
  addr.sin_family       = AF_INET;
  addr.sin_addr.s_addr  = inet_addr(m_strDstIpAddr);
  addr.sin_port         = htons(m_nTxPort);

  int nMsgLen = 8;
  char pTxBuffer[8];
  *((DWORD*) &pTxBuffer[ 0]) = 0x11223344;
  *((DWORD*) &pTxBuffer[ 4]) = 0;

  int nSent = sendto(sSocket, pTxBuffer, nMsgLen, 0, (struct sockaddr *) &addr, sizeof(addr));
  Sleep(10);   // <- this seems to be necessary

  if (nSent != nMsgLen)
  {
     CString s = "error sending HELO\n";
     AfxMessageBox(s);
  } 
  closesocket(sSocket);

}

没有Sleep(),代码不会发送任何内容,但它不会返回任何错误。使用Sleep()它可以工作。此外,这是在发布版本中发生的,当编译为调试时,代码也可以在没有Sleep()的情况下工作。

好像,在最后发送消息之前,closesocket()关闭了套接字,但我认为sendto()是一个同步函数。我尝试使用SO_LINGER,但这不适用于SOCK_DGRAM套接字。

由于代码在DLL中,我不能在ctor中创建套接字并在dtor中删除它,因为可能从不同的线程上下文调用SendHello(),我想避免使代码过于复杂

感谢您的帮助

1 个答案:

答案 0 :(得分:0)

使用UDP,发送方和接收方之间没有数据排序,并且使用UDP数据报套接字发送的数据不能保证到达。在您的情况下,所有睡眠都在为数据提供足够的时间到达另一端。如果要确认接收和错误检查,则可以为UDP编写方案或使用TCP。实际上,您可以完全关闭服务器,即使没有人在监听,您的客户也会愉快地发出UDP数据包而不会出错。

确保连接,查看connect()。没有什么可以阻止使用UDP连接,然后您可以使用send()recv()。