我创建一个UDP套接字(AF_INET
,SOCK_DGRAM
,IPPROTO_UDP
通过Winsock的),并试图recvfrom
在此套接字上,但它总是返回-1,我得到WSAEINVAL(10022).为什么?
当我bind()
的端口,这不会发生,但我已经读到绑定客户端的套接字是非常蹩脚的.
我正在向我的服务器发送数据,该服务器回答或至少尝试过.
Inc::STATS CConnection::_RecvData(sockaddr* addr, std::string &strData) { int ret; // return code int len; // length of the data int fromlen; // sizeof(sockaddr) char *buffer; // will hold the data char c; //recv length of the message fromlen = sizeof(sockaddr); ret = recvfrom(m_InSock, &c, 1, 0, addr, &fromlen); if(ret != 1) { #ifdef __MYDEBUG__ std::stringstream ss; ss << WSAGetLastError(); MessageBox(NULL, ss.str().c_str(), "", MB_ICONERROR | MB_OK); #endif return Inc::ERECV; } ...
这是我刚才写的一个工作示例,它bind()
在没有客户端调用的情况下工作:
#pragma comment(lib, "Ws2_32.lib") #define WIN32_LEAN_AND_MEAN #include#include #include using namespace std; int main() { SOCKET sock; addrinfo* pAddr; addrinfo hints; sockaddr sAddr; int fromlen; const char czPort[] = "12345"; const char czAddy[] = "some ip"; WSADATA wsa; unsigned short usWSAVersion = MAKEWORD(2,2); char Buffer[22] = "TESTTESTTESTTESTTEST5"; int ret; //Start WSA WSAStartup(usWSAVersion, &wsa); //Create Socket sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); //Resolve host address memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_protocol = IPPROTO_UDP; hints.ai_socktype = SOCK_DGRAM; if(getaddrinfo(czAddy, czPort, &hints, &pAddr)) { std::cerr << "Could not resolve address...\n"; std::cin.get(); return 1; } //Start Transmission while(1) { ret = sendto(sock, Buffer, sizeof(Buffer), 0, pAddr->ai_addr, pAddr->ai_addrlen); if(ret != sizeof(Buffer)) { std::cerr << "Could not send data\n"; std::cin.get(); return 1; } fromlen = sizeof(SOCKADDR); ret = recvfrom(sock, Buffer, sizeof(Buffer), 0, &sAddr, &fromlen); if(ret != sizeof(Buffer)) { std::cout << "Could not receive data - error: " << WSAGetLastError() << std::endl; std::cin.get(); return 1; } Buffer[ret-1] = '\0'; std::cout << "Received: " << Buffer << std::endl; } return 0; }
Warren Young.. 42
使用UDP,您必须bind()
使用客户端中的套接字,因为UDP是无连接的,因此堆栈无法知道将数据报传递给特定端口的程序.
如果recvfrom()
没有bind()
,你基本上要求堆栈为你的程序提供发送到该计算机的所有UDP数据报.由于堆栈只向一个程序提供数据报,这将破坏DNS,Windows的网络邻居,网络时间同步....
您可能已经在网上某处读过客户端绑定很蹩脚,但该建议仅适用于TCP连接.
使用UDP,您必须bind()
使用客户端中的套接字,因为UDP是无连接的,因此堆栈无法知道将数据报传递给特定端口的程序.
如果recvfrom()
没有bind()
,你基本上要求堆栈为你的程序提供发送到该计算机的所有UDP数据报.由于堆栈只向一个程序提供数据报,这将破坏DNS,Windows的网络邻居,网络时间同步....
您可能已经在网上某处读过客户端绑定很蹩脚,但该建议仅适用于TCP连接.
您的其他代码示例有效,因为您sendto
之前使用过recvfrom
.如果UDP套接字未绑定且已在其上调用sendto
或被connect
调用,则系统将自动为您绑定它,因此recvfrom
稍后调用将成功.recvfrom
不会绑定套接字,因为此调用期望套接字已被绑定,否则将引发错误.