首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >是否必须在客户端程序中绑定UDP套接字才能接收数据?(我总是得到WSAEINVAL)

是否必须在客户端程序中绑定UDP套接字才能接收数据?(我总是得到WSAEINVAL)
EN

Stack Overflow用户
提问于 2010-06-17 04:44:28
回答 3查看 73.2K关注 0票数 34

我正在通过Winsock创建一个UDP (AF_INETSOCK_DGRAMIPPROTO_UDP),并尝试在这个套接字上执行recvfrom,但它总是返回-1,并且我得到了WSAEINVAL (10022)。为什么?

当我bind()端口时,这是不会发生的,但我读到绑定客户端的套接字是非常差劲的。

我正在向我的服务器发送数据,它会响应,或者至少会尝试。

代码语言:javascript
复制
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()就可以工作:

代码语言:javascript
复制
#pragma comment(lib, "Ws2_32.lib")

#define WIN32_LEAN_AND_MEAN

#include <WS2tcpip.h>
#include <Windows.h>
#include <iostream>

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;
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-06-17 07:03:45

使用UDP时,您必须在客户端bind()套接字,因为UDP是无连接的,所以堆栈没有其他方法来知道为特定端口将数据报发送到哪个程序。

如果您可以在没有bind()的情况下使用recvfrom(),那么您实际上就是在要求堆栈将所有发送到该计算机的UDP数据报提供给您的程序。由于堆栈只向一个程序发送数据报,这将破坏DNS、Windows的网络邻居、网络时间同步……

您可能已经在网上读到过客户端中的绑定很差劲,但这个建议只适用于TCP连接。

票数 53
EN

Stack Overflow用户

发布于 2013-01-10 02:00:47

您的其他代码样例之所以有效,是因为您在使用recvfrom之前使用了sendto。如果未绑定UDP套接字,并且在其上调用了sendtoconnect,则系统将自动为您绑定该套接字,因此稍后的recvfrom调用将成功。recvfrom不会绑定套接字,因为此调用期望套接字已经绑定,否则将抛出错误。

票数 45
EN

Stack Overflow用户

发布于 2010-06-17 05:01:26

Here它说:

参数

S in:标识绑定套接字的描述符。

..。

返回值

WSAEINVAL:尚未使用绑定绑定套接字,或者指定了未知标志,或者为启用了SO_OOBINLINE的套接字指定了MSG_OOB,或者(仅适用于字节流样式的套接字) len为零或负。

据我所知,UDP套接字不需要绑定,因为堆栈会为您进行绑定调用。我猜这是Windows的事情,需要在recvfrom调用中使用的套接字上绑定。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3057029

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档