2017-05-31 4 views
-3

Hier ist meine erste Frage in dieser großen Website.Winsock Fehler 10022 in hören

Ich bin ein einfacher Server zu schreiben, zu erhalten die Portnummer des Benutzers bilden:

#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; 
     } 
     ..... 

ich den Fehler 10022 erhalten, wenn Funktion aufrufen hören, und ich kann nicht das ungültige Argument sehe ich vorbei bin auf die Funktion.

+0

Wenn die Fehlermeldung von dem 'hören()' dann sieht es aus wie Ihre 'socket()' Aufruf: wie (mit RAII, werfen Ausnahmen auf Fehler, usw.) - ich würde etwas mehr C++ vorschlagen 'socketbind()' führt eine Rückgabe aus, so dass 'bind()' nie aufgerufen wird. https://msdn.microsoft.com/en-us/library/windows/desktop/ms739168(v=vs.85).aspx WSAEINVAL bedeutet, dass der Socket nicht mit bind gebunden wurde. –

Antwort

1

Fehlercode 10022 ist WSAEINVAL:

Invalid argument.
Einige ungültige Argumente wurden angegeben (z. B. Angabe einer ungültigen Ebene für die Funktion setsockopt). In einigen Fällen bezieht es sich auch auf den aktuellen Status des Sockets - z. B. Aufruf von accept an einem Socket, der nicht abhört.

Per der listen() documentation:

Rückgabewert

Wenn kein Fehler auftritt, Null listen kehrt zurück. Andernfalls wird ein Wert von SOCKET_ERROR zurückgegeben, und ein bestimmter Fehlercode kann durch Aufrufen von WSAGetLastError abgerufen werden.

...

WSAEINVAL
Der Sockel wurde mit bind

In Ihrem socketBind() Verfahren nicht gebunden, wenn socket() erfolgreich ist, die Sie anrufen return, bevor Sie bind() rufen , also ist die Steckdose nie gebunden. Sie müssen die return Anweisung im 1. else Block entfernen. Wenn bind() erfolgreich ist, ruft der zweite else Block return auf, bevor er freeaddrinfo() aufruft, also müssen Sie das ebenfalls beheben.

Try this:

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

aber sagt, dass Ihre Klasse ist eine sehr gute Arbeit bei der Bereinigung im Allgemeinen nicht zu tun.

#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"); 
    } 

    ... 
};