我有一个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(),我想避免使代码过于复杂
感谢您的帮助
答案 0 :(得分:0)
使用UDP,发送方和接收方之间没有数据排序,并且使用UDP数据报套接字发送的数据不能保证到达。在您的情况下,所有睡眠都在为数据提供足够的时间到达另一端。如果要确认接收和错误检查,则可以为UDP编写方案或使用TCP。实际上,您可以完全关闭服务器,即使没有人在监听,您的客户也会愉快地发出UDP数据包而不会出错。
确保连接,查看connect()。没有什么可以阻止使用UDP连接,然后您可以使用send()recv()。