Я должен обязать сокет UDP в своей клиентской программе получать данные? (Я всегда получаю WSAEINVAL),

Я создаю сокет 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 <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;
}
28
задан Warren Young 18 February 2016 в 11:44
поделиться

2 ответа

С UDP вы должны bind () сокет в клиенте, потому что UDP не поддерживает соединение, поэтому у стека нет другого способа узнать, какой программа для доставки дейтаграмм для определенного порта.

Если бы вы могли recvfrom () без bind () , вы, по сути, просили бы стек передать вашей программе все дейтаграммы UDP, отправляемые на этот компьютер. Поскольку стек доставляет дейтаграммы только одной программе, это нарушит DNS, сетевое окружение Windows, синхронизацию сетевого времени ....

Возможно, вы читали где-то в сети, что привязка в клиенте неуместна, но это только совет. применяется к TCP-соединениям.

42
ответ дан 28 November 2019 в 02:35
поделиться

Здесь говорится следующее:

Параметры

s [in]: дескриптор, идентифицирующий связанный сокет.

...

Возвращаемое значение

WSAEINVAL: сокет не был связан с привязкой, или был указан неизвестный флаг, или MSG_OOB был указан для сокета с включенным SO_OOBINLINE, или (для стиля байтового потока только сокеты) len было нулевым или отрицательным.

Насколько я помню, привязка не требуется для сокета UDP, потому что вызов привязки выполняется за вас стеком. Я предполагаю, что это вещь Windows, требующая привязки к сокету, используемому в вызове recvfrom.

1
ответ дан 28 November 2019 в 02:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: