首页 文章

winsock错误10022在听

提问于
浏览
-3

这是我在这个伟大的网站上的第一个问题 .

我正在编写一个简单的服务器,从用户那里获取端口号:

#include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream>
#include <string>
#include <cstring>

class socketConexion { 
private: 
    WSADATA wsaData; 
    int iResultado; 
    SOCKET socketServidor = INVALID_SOCKET;  socket servidor 
    SOCKET socketCliente = INVALID_SOCKET; 
    struct sockaddr *clienteSockaddr;
    struct addrinfo *socketResultado = NULL;
    struct addrinfo datosServidor;
    std::string puertoUsuario;
    char clienteIPV4[LONG_IPV4];
public:
    int iniciarWinsock () { 
        iResultado = WSAStartup(MAKEWORD(2,2), &wsaData);
        printf ("Inicializando Winsock2 \n");
        if (iResultado != 0) { 
            printf ("Error al iniciar Winsock2: %d\n", iResultado);
            return 1;
        else {
            printf ("Winsock2 Inicializado\n");
            return 0;
        }
    }
    int obtenerDirServidor () {
        printf ("Introduzca puerto: ");
        std::cin >> puertoUsuario;
        printf ("Obteniendo datos de servidor.\n");
        ZeroMemory(&datosServidor, sizeof(datosServidor));
        datosServidor.ai_family = AF_INET;
        datosServidor.ai_socktype = SOCK_STREAM;
        datosServidor.ai_protocol = IPPROTO_TCP;
        datosServidor.ai_flags = AI_PASSIVE;
        iResultado = getaddrinfo(NULL, (const char*)puertoUsuario.c_str(), &datosServidor, &socketResultado);
        if (iResultado != 0) {
            printf ("Error al obtener dirección de servidor: %d\n", iResultado);
            WSACleanup();
            return 1;
        }
        else {
            printf ("Dirección de servidor obtenida.\n");
            return 0;
        }
    }
    int socketBind () {
        socketServidor = socket(socketResultado->ai_family, socketResultado->ai_socktype, socketResultado->ai_protocol);
        if (socketServidor == INVALID_SOCKET) {
            printf ("Error al crear socket: %d\n", WSAGetLastError ());
            freeaddrinfo (socketResultado);
            WSACleanup();
            return 1;
        }
        else {
            printf ("Socket creado correctamente.\n");
            return 0;
        }
        iResultado = bind(socketServidor, socketResultado->ai_addr, (int)socketResultado->ai_addrlen);
        if (iResultado == SOCKET_ERROR) {
            printf ("Error al direccionar socket: %d\n", WSAGetLastError());
            freeaddrinfo (socketResultado);
            closesocket(socketServidor);
            WSACleanup();
            return 1;
        }
        else {
            printf ("Socket direccionado correctamente. \n");
            return 0;   
        }
        freeaddrinfo (socketResultado);
    }
    int socketListen (){
        iResultado = listen(socketServidor, SOMAXCONN);
        if (iResultado == SOCKET_ERROR) {
            printf ("Error al poner socket a la escucha socket: %d\n", WSAGetLastError());
            closesocket(socketServidor);
            WSACleanup();
            return 1;
        }
        else {
            printf ("Esperando conexión..... %d\n");
            return 0;
        }
         .....

我在调用listen函数时得到错误10022,我看不到传递给函数的无效参数 .

1 回答

  • 1

    错误代码10022是WSAEINVAL

    无效的参数 . 提供了一些无效参数(例如,为setsockopt函数指定了无效级别) . 在某些情况下,它还引用套接字的当前状态 - 例如,在未侦听的套接字上调用accept .

    根据listen() documentation

    返回值如果没有错误发生,则listen返回零 . 否则,返回值SOCKET_ERROR,并且可以通过调用WSAGetLastError来检索特定的错误代码 . ... WSAEINVAL套接字尚未绑定绑定

    socketBind() 方法中,如果 socket() 成功,则在调用 bind() 之前调用 return ,因此套接字永远不会被绑定 . 您需要删除第一个 else 块中的 return 语句 . 此外,如果 bind() 成功,则第二个 else 块在调用 freeaddrinfo() 之前调用 return ,因此您还需要修复它 .

    试试这个:

    int socketBind () {
        socketServidor = socket(socketResultado->ai_family, socketResultado->ai_socktype, socketResultado->ai_protocol);
        if (socketServidor == INVALID_SOCKET) {
            printf ("Error al crear socket: %d\n", WSAGetLastError ());
            freeaddrinfo (socketResultado);
            WSACleanup();
            return 1;
        }
    
        printf ("Socket creado correctamente.\n");
    
        iResultado = bind(socketServidor, socketResultado->ai_addr, (int)socketResultado->ai_addrlen);
        if (iResultado == SOCKET_ERROR) {
            printf ("Error al direccionar socket: %d\n", WSAGetLastError());
            freeaddrinfo (socketResultado);
            closesocket(socketServidor);
            WSACleanup();
            return 1;
        }
    
        printf ("Socket direccionado correctamente. \n");
    
        freeaddrinfo (socketResultado);
        return 0;   
    }
    

    话虽这么说,你的 class 在整体清理方面做得并不好 . 我会建议更像C的东西(使用RAII,在错误上抛出异常等):

    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <iostream>
    #include <string>
    #include <system_error>  
    #include <memory>
    
    class socketError : public std::system_error
    {
    public:
        explicit socketError(int err, const std::string &msg)
            : std::system_error(err, std::system_category(), msg + ": " + std::to_string(err))
        {
        }
    };
    
    void throwSocketError(int err, const std::string &msg)
    {
        std::cout << msg << ": " << err << std::endl;
        throw socketError(err, msg);
    }
    
    class wsaInit
    {
    public:
        wsaInit() {
            int iResultado = WSAStartup(MAKEWORD(2,2), &wsaData);
            printf ("Inicializando Winsock2 \n");
            if (iResultado != 0)
                throwSocketError(iResultado, "Error al iniciar Winsock2");
            printf ("Winsock2 Inicializado\n");
        }
    
        ~wsaInit() {
            WSACleanup();
        }
    
        wsaInit(const wsaInit &) = delete;
        wsaInit& operator=(const wsaInit &) = delete;
    };
    
    class socketWrapper
    {
    private:
        SOCKET sckt;
    
    public:
        socketWrapper() : sckt(INVALID_SOCKET) {}
        explicit socketWrapper(SOCKET initialSocket) : sckt(initialSocket) {}
        ~socketWrapper() { reset(); }
    
        socketWrapper(const socketWrapper &) = delete; 
        socketWrapper& operator=(const socketWrapper &) = delete; 
    
        void reset(SOCKET newSocket = INVALID_SOCKET) { if (sckt != INVALID_SOCKET) closesocket(sckt); sckt = newSocket; }
    
        operator SOCKET() const { return sckt; }
        bool operator !() const { return (sckt == INVALID_SOCKET); }
    };
    
    class socketConexion { 
    private: 
        wsaInit wsa; 
        socketWrapper socketServidor;
        socketWrapper socketCliente; 
        std::unique_ptr<struct addrinfo> socketResultado;
        ...
    
    public:
        socketConexion(const socketConexion &) = delete; 
        socketConexion& operator=(const socketConexion &) = delete; 
    
        void obtenerDirServidor() {
            socketResultado.reset();
    
            printf ("Introduzca puerto: ");
    
            std::string puertoUsuario;
            std::cin >> puertoUsuario;
    
            printf ("Obteniendo datos de servidor.\n");
    
            struct addrinfo datosServidor;
            ZeroMemory(&datosServidor, sizeof(datosServidor));
            datosServidor.ai_family = AF_INET;
            datosServidor.ai_socktype = SOCK_STREAM;
            datosServidor.ai_protocol = IPPROTO_TCP;
            datosServidor.ai_flags = AI_PASSIVE;
    
            struct addrinfo *pResultado;
    
            int iResultado = getaddrinfo(NULL, puertoUsuario.c_str(), &datosServidor, &pResultado);
            if (iResultado != 0)
                throwSocketError(iResultado, "Error al obtener dirección de servidor");
    
            socketResultado.reset(pResultado);
    
            std::cout << "Dirección de servidor obtenida." << std::endl;
        }
    
        void socketBind () {
            socketServidor.reset();
    
            if (!socketResultado)
                obtenerDirServidor();
    
            socketServidor.reset(socketResultado->ai_family, socketResultado->ai_socktype, socketResultado->ai_protocol));
            if (!socketServidor) {
                int iError = WSAGetLastError();
                socketResultado.reset();
                throwSocketError(iError, "Error al crear socket");
            }
    
            printf("Socket creado correctamente.\n");
    
            int iResultado = ::bind(socketServidor, socketResultado->ai_addr, (int)socketResultado->ai_addrlen);
            if (iResultado == SOCKET_ERROR) {
                iResultado = WSAGetLastError();
                socketResultado.reset();
                throwSocketError(iResultado, "Error al direccionar socket");
            }
    
            socketResultado.reset();
    
            printf ("Socket direccionado correctamente. \n");
        }
    
        void socketListen() {
            if (!socketServidor)
                socketBind();
    
            int iResultado = listen(socketServidor, SOMAXCONN);
            if (iResultado == SOCKET_ERROR)
                throwSocketError(WSAGetLastError(), "Error al poner socket a la escucha socket");
    
            printf ("Esperando conexión.....\n");
        }
    
        ...
    };
    

相关问题