UDP套接字的WSASend在没有可用目标时触发FD_READ
WSASend for UDP socket triggers FD_READ when no destination available
我正在为UDP套接字类编写C++代码,以处理基本操作(如连接、发送和接收数据)。我尝试将网络事件机制与WSAEventSelect一起用于与套接字相关联的这些基本操作。当我使用WSASend将数据发送到接收数据的(UDP)目的地时,一切都很顺利。但是,当我使用WSASend将数据发送到不存在(UDP)或无法通过网络访问的目的地时,我会触发FD_READ事件。这当然会导致严重的问题,因为没有实际的数据可以接收!!
我无法解释为什么会发生这种事——有什么想法吗
也许我做错了什么,以下是我代码的相关部分:
WSADATA m_wsaData ;
SOCKET m_Socket ;
WSAEVENT m_SocketEvent ;
if(WSAStartup(MAKEWORD(2,2), &m_wsaData) != 0)
{
// some error
}
// Create a new socket to receive datagrams on
struct addrinfo hints, *res = NULL ;
int rc ;
memset(&hints, 0, sizeof(hints)) ;
hints.ai_family = AF_UNSPEC ;
hints.ai_socktype = SOCK_DGRAM ;
hints.ai_protocol = IPPROTO_UDP ;
rc = getaddrinfo("SomePC", "3030", &hints, &res) ;
if(rc == WSANO_DATA)
{
// some error
}
if ((m_Socket = WSASocket(res->ai_family, res->ai_socktype, res->ai_protocol, NULL, 0, 0)) == INVALID_SOCKET)
{
// some error
}
// create event and associate it with the socket
m_SocketEvent = WSACreateEvent() ;
if(m_SocketEvent == WSA_INVALID_EVENT)
{
// some error
}
// associate only the following events: close, read, write
if(SOCKET_ERROR == WSAEventSelect(m_Socket, m_SocketEvent, FD_CLOSE+FD_READ+FD_WRITE))
{
// some error
}
// connect to a server
int ConnectRet = WSAConnect(m_Socket, (SOCKADDR*)res->ai_addr, res->ai_addrlen, NULL, NULL, NULL, NULL) ;
if(ConnectRet == SOCKET_ERROR)
{
// some error
}
然后,每当我试图通过套接字将一些数据发送到无法侦听或无法访问的(UDP套接字)目的地时,我总是会触发FD_READ:
char buf[32] ; // some data to send...
WSABUF DataBuf;
DataBuf.len = 32;
DataBuf.buf = (char*)&buf;
DWORD NumBytesActualSent ;
if( SOCKET_ERROR == WSASend(m_Socket, &DataBuf, 1, &NumBytesActualSent,0,0,0))
{
if(WSAGetLastError() == WSAEWOULDBLOCK) // non-blocking socket - wait for send ok ?
{
// handle WSAEWOULDBLOCK...
}
else
{
// some error
return ;
}
}
int ret = WSAWaitForMultipleEvents(1, &m_SocketEvent, FALSE, INFINITE, FALSE) ;
if(ret == WAIT_OBJECT_0)
{
WSANETWORKEVENTS NetworkEvents ;
ZeroMemory(&NetworkEvents, sizeof(NetworkEvents)) ;
if(SOCKET_ERROR == WSAEnumNetworkEvents(m_Socket, m_SocketEvent, &NetworkEvents))
{
return ; // some error
}
if(NetworkEvents.lNetworkEvents & FD_READ) // Read ?
{
if(NetworkEvents.iErrorCode[FD_READ_BIT] != 0) // read not ok ?
{
// some error
}
else
{
TRACE("Read Event Triggered ! - Why ? ? ? ? ? ? ?n") ;
}
}
}
任何帮助或见解都将不胜感激!谢谢Amit C.
检查实际情况的最简单方法是使用Wireshark捕获数据包。我附近没有Windows PC为您提供完整的示例,但我猜这是一种正常的行为-您试图发送UDP数据报,但它被路由器丢弃(找不到主机)或被服务器拒绝(套接字关闭);ICMP消息会被发送回来通知您失败,这就是您接收并获得事件的原因。由于没有实际的用户数据,底层堆栈转换ICMP消息,并通过WSARecv()返回代码为您提供适当的错误消息。"false"FD_READ事件是必要的,因为UDP是无连接协议,并且没有其他方式来通知网络状态。只需为WSARecv()添加错误处理,您的代码就会正常工作。
相关文章:
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- C++A*算法并不总是在路径中具有目标节点
- 基于树莓pi的tensorflow lite量化ssd目标检测
- 为测试目标创建具有不同源文件夹的文件
- 使用源向量作为目标
- 是否可以用C++/WinRT将windows 10.0.14393作为目标
- 在 CMake 中为每个目标设置编译器/链接器标志
- qmake:检测目标位宽(32 位或 64 位)
- 如何在 CMake 中对目标依赖项进行分组?
- 我的目标是编写一个程序来计算和存储字符串在字符数组中出现的位置
- 如何为包含头文件的目标编写生成文件?
- 线性优化目标函数中的绝对值
- 制作文件:没有规则来制定目标:如何设置正确的规则?
- 字符串函数在目标C++上运行时C++返回空
- 如何定义自定义生成配置类型,其中通常是.exe的目标改为 DLL
- 请求最简单的 OpenMP 目标 GPU 示例
- LLVM 编译:目标的配方 '../lib/IR/Release+Asserts/Intrinsics.gen.tmp' failed
- 当目标指针不是基类的类型时,为什么允许dynamic_cast为多态类生成 null 指针?
- 我应该如何在没有变量的情况下将相同的参数传递给 CMAKE 中的多个目标?
- CMake 错误 - 目标 foo INTERFACE_SOURCES属性包含在源目录中以前缀为前缀的路径