recv (Winsock) 函数挂起,但数据可用
recv (winsock) function hangs, though data is available
我正在使用 winsock 套接字 api 发送具有非常高端口号的 udp 数据包,我希望在目的地未使用。我的目的是接收一个带有目标无法访问/端口无法访问消息的 icmp 数据包。我创建了两个套接字,一个是我发送 UDP 数据包的套接字,另一个是我期待 icmp 数据包的套接字。发送成功。目的地也返回ICMP回复,我可以在wireshark上验证。现在,当我执行 recv 以接收数据时,recv 函数挂起。我的目标是从recv函数读取数据,这不会发生。
任何有助于理解/修复此行为的帮助将不胜感激。提前谢谢。
我在这里附加代码片段...
void sendPacket(unsigned int socketFd, char *packet, char* remoteIP, char* pingType)
{
int nsent = -1;
int rc = -1;
struct addrinfo hints, *res;
memset(&hints, 0, sizeof(struct addrinfo));
if (strcasecmp(pingType, "UDP")==0)
{
hints.ai_flags = AI_CANONNAME; /* always return canonical name */
hints.ai_family = AF_INET; /* 0, AF_INET, AF_INET6, etc. */
hints.ai_socktype = SOCK_DGRAM; /* 0, SOCK_STREAM, SOCK_DGRAM, etc. */
}
rc = getaddrinfo(remoteIP, NULL, &hints, &res);
if ( rc != 0)
{
printf("... Function: %stError setting remote address. Exiting. ... n", __FUNCTION__);
exit(-1);
}
if (strcasecmp(pingType, "UDP")==0)
{
((struct sockaddr_in *)res->ai_addr)->sin_port = htons(34344);
strcpy(packet, "TIMESTAMP");
}
do
{
if (strcasecmp(pingType, "UDP")==0)
{
nsent=sendto(socketFd, packet, strlen(packet), 0, (struct sockaddr *)res->ai_addr, (socklen_t)res->ai_addrlen);
if (nsent < 0)
{
continue;
}
}
}while(nsent < 0);
return;
}
double receivePacket(int socketFd, struct timeval* tvSend, pingReply** lastReplyNode, char* pingType)
{
ssize_t nRecv = -1;
double rc = -1;
char recvbuf[1024];
do
{
nRecv = recv(socketFd, (char *)recvbuf, 1024, 0);
}
while(nRecv < 0);
if (nRecv < 0)
{
return -1;
}
rc = processPacket(recvbuf, nRecv, tvSend, lastReplyNode, pingType);
if (rc == -1)
{
printf("... Function: %stReceiving error in Data/Protocol ...n", __FUNCTION__);
return -1;
}
return rc;
}
void createSocket(unsigned int *sendSocketFd, unsigned int *receiveSocketFd, char *pingType)
{
#ifdef _WIN32
WORD wVersionRequested;
WSADATA wsaData;
int err;
/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
{
/* Tell the user that we could not find a usable */
/* Winsock DLL. */
printf("WSAStartup failed with error: %dn", err);
exit(-1);
}
#endif
#ifdef _WIN32
if (strcasecmp(pingType, "UDP")==0)
{
int rc = -1;
struct sockaddr_in src_address;
unsigned long int length;
int optval = 1;
DWORD Length;
OSVERSIONINFO g_OSVersionInfo;
BOOLEAN g_IsWindowsLonghorn = TRUE;
BOOLEAN g_UseFtosToSetTos = TRUE;
int ret, iVal=0;
unsigned int sz = sizeof(iVal);
g_OSVersionInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO);
GetVersionEx( &g_OSVersionInfo );
if( g_OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
{
if( g_OSVersionInfo.dwMajorVersion >= 6 )
{
g_IsWindowsLonghorn = TRUE;
g_UseFtosToSetTos = TRUE;
}
}
*receiveSocketFd = INVALID_SOCKET;
*receiveSocketFd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (*receiveSocketFd < 0)
{
printf("Function: %stReceiving Socket creation error.tErrNo %d. ...n", __FUNCTION__, WSAGetLastError());
exit(-1);
}
src_address.sin_family=AF_INET;
src_address.sin_addr.s_addr=inet_addr("x.x.x.x");
src_address.sin_port=htons(0);
rc = bind((SOCKET)*receiveSocketFd,(struct sockaddr *)&src_address,sizeof(src_address));
if (rc < 0)
{
printf("Function: %stReceiving Socket bind error.tErrNo %d. ...n", __FUNCTION__, WSAGetLastError());
exit(-1);
}
iVal = 30000; // in milliseconds
ret = setsockopt(*receiveSocketFd, SOL_SOCKET, SO_RCVTIMEO, (char *)&iVal, sz);
if (ret == SOCKET_ERROR)
{
printf("%dn", WSAGetLastError());
return; // Temporary
}
rc = WSAIoctl((SOCKET)*receiveSocketFd, SIO_RCVALL, &optval, sizeof(optval), NULL, 0, &length, NULL, NULL);
if (rc == SOCKET_ERROR)
{
printf("Function: %stReceiving Socket ioctl error.tErrNo %d. ...n", __FUNCTION__, WSAGetLastError());
exit(-1);
}
printf("Function: %streceiveSocketFd %d ...n", __FUNCTION__, *receiveSocketFd);
}
else
{
*receiveSocketFd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (*receiveSocketFd < 0)
{
printf("Function: %stReceiving Socket creation error.tErrNo %d. ...n", __FUNCTION__, WSAGetLastError());
exit(-1);
}
printf("Function: %streceiveSocketFd %d ...n", __FUNCTION__, *receiveSocketFd);
}
#endif
#ifndef _WIN32
unsigned int size = 1024; /* OK if setsockopt fails */
setsockopt(*receiveSocketFd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
#else
char size[5] = "1024"; /* OK if setsockopt fails */
setsockopt(*receiveSocketFd, SOL_SOCKET, SO_RCVBUF, size, sizeof(size));
#endif
if (strcasecmp(pingType, "UDP")==0)
{
*sendSocketFd = socket(AF_INET, SOCK_DGRAM, 0);
if (*sendSocketFd < 0)
{
printf("Send Socket creation error.");
exit(-1);
}
printf("Function: %stsendSocketFd %d ...n", __FUNCTION__, *sendSocketFd);
}
return;
}
除非在UDP意义上连接了套接字,否则您不会获得"目的地无法访问",然后您不会通过recv()获取它,而是从可能的后续send()中获取它作为errno值。
相关文章:
- 挂起和取消挂起一个文件DLL
- 如何防止C++遗留代码中的挂起指针
- 为什么所有C++编译器都会崩溃或挂起此代码
- 我编写了代码将十进制分数转换为其二进制等效数.它编译得很好,但在执行时挂起
- 构建挂起,即使是适度的文件大小
- 循环挂起迭代的 std::擦除 on std::list
- Poco::Net::FTPClientSession 在 open() 方法上挂起 129 秒,如果 ftp 主机不存
- Node.js fs.open() 在尝试打开 4 个以上的命名管道 (FIFO) 后挂起
- 从不同进程中的另一个线程挂起/恢复线程或进程
- Boost (Beast) websocket:同步写入挂起
- 为什么析构函数挂起
- 使用互斥会挂起程序
- 在C++和 Python 程序中使用命名管道的 IPC 挂起
- 设置变量时C++程序挂起
- 第一次尝试使用new动态创建结构数组,程序挂起没有错误
- 从stdin读取时子进程挂起(fork/dup2竞争条件)
- 将空数据写入非阻塞套接字会导致epoll_wait挂起
- 发送数据后,SMTP客户端挂起
- recv (Winsock) 函数挂起,但数据可用
- 为什么我的c++ cmd屏幕挂起时,我试图访问一个文件来存储数据