2017-05-31 52 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"); 
    } 

    ... 
};