【发布时间】:2014-09-05 08:06:16
【问题描述】:
我正在为 Windows 桌面/服务器编写一个 UDP 服务器应用程序。
我的代码使用windows建议的WSA API如下(这是我简化的receivePacket方法):
struct Packet
{
unsigned int size;
char buffer[MAX_SIZE(1024)];
}
bool receivePacket(Packet packet)
{
WSABUFFER wsa_buffer[2];
wsa_buffer[0].buf = &packet.size;
wsa_buffer[0].len = sizeof(packet.size);
wsa_buffer[1].buf = packet.buffer;
wsa_buffer[1].len = MAX_SIZE;
bool retval = false;
int flags = 0;
int recv_bytes = 0;
inet_addr client_addr;
int client_addr_len = sizeof(client_addr);
if(WSARecvFrom(_socket, wsa_buffer, sizeof(wsa_buffer)/sizeof(wsa_buffer[0]), &bytes_recv, &flags, (sockaddr *)&client_addr, &client_addr_len, NULL, NULL) == 0)
{
//Packet received successfully
}
else
{
//Report
}
}
现在,当我试图优雅地关闭我的应用程序时,不是在网络方面,而是在应用程序方面(通过所有的 d'tors 和东西),我试图取消阻止这个调用。
为此,我调用了shutdown(_socket, SD_BOTH) 方法。不幸的是,关闭自身的调用BLOCKS!
在阅读了 MSDN 中所有可能的页面后,我没有找到任何关于为什么会发生这种情况、其他解决问题的方法或任何出路的参考。
我检查的另一件事是使用SO_RCVTIMEO。令人惊讶的是,这个 sockopt 也没有按预期工作。
我的代码/方法有什么问题吗?
【问题讨论】:
-
您是否在程序开始时初始化了 WSA? SO_RCVTIMEO 的行为如何?可以添加socket创建和选项设置代码吗?
-
这几乎是不可能的。该代码是在另一台未连接到网络的计算机上编写的。我确实初始化了WSA,初始化成功。这是我的程序创建的唯一套接字。我在调用绑定之后使用 setsockopt(_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) ,它返回零(成功)
-
我在 MSDN 中发现了有关 SO_RCVTIMEO 选项的信息,这可能解释了为什么它的行为不像您预期的那样:“用于阻止接收呼叫的超时,以毫秒为单位。此选项的默认值为零,这表示接收操作不会超时。如果阻塞接收调用超时,则连接处于不确定状态,应关闭。如果使用 WSASocket 函数创建套接字,则 dwFlags 参数必须设置 WSA_FLAG_OVERLAPPED 属性超时才能正常工作。否则超时永远不会生效。"
-
你读过这个吗:msdn.microsoft.com/en-us/library/windows/desktop/… 顺便说一句? cmets也有点担心。
-
您是否尝试过仅使用
SD_RECEIVE而不是SD_BOTH?为什么要shutdown一个UDP套接字?
标签: c++ windows sockets networking udp