2017-05-31 183 views
-3

這是我在這個偉大的網站的第一個問題。winsock錯誤10022在聽

我寫一個簡單的服務器,獲取端口號形成用戶:

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

調用聽功能,當我得到錯誤10022,我看不到我傳遞到無效的參數功能。

+0

如果錯誤消息來自'listen()',那麼它看起來像你的'socket()'調用'socketbind()'不返回,所以'bind()'永遠不會被調用。 https://msdn.microsoft.com/en-us/library/windows/desktop/ms739168(v=vs.85).aspx WSAEINVAL表示套接字尚未綁定綁定。 –

回答

1

錯誤代碼10022是WSAEINVAL

參數無效。
提供了一些無效的參數(例如,指定setsockopt函數的無效等級)。 在某些情況下,它也指代套接字的當前狀態 - 例如,在未偵聽的套接字上調用accept

listen() documentation

返回值

如果沒有出現錯誤,listen返回零。否則,返回SOCKET_ERROR的值,通過調用WSAGetLastError可以檢索到特定的錯誤代碼。

...

WSAEINVAL
套接字尚未綁定bind

在你socketBind()方法,如果socket()是成功的,您呼叫return打電話bind()前,所以套接字永遠不會綁定。您需要刪除第一個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; 
} 

話雖這麼說,你的類不是一般的清理做了很好的工作。我會建議更多的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"); 
    } 

    ... 
};