Ошибка 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 при вызове функции прослушивания и не вижу неверный аргумент, который передаю функции.

-3

Решение

Код ошибки 10022 WSAEINVAL:

Недействительным аргумент.
Был указан некоторый неверный аргумент (например, указание неверного уровня для setsockopt функция). В некоторых случаях это также относится к текущему состоянию сокета— например, позвонив accept на сокете, который не слушает.

В соответствии с listen() документация:

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

Если ошибки не возникает, listen возвращает ноль. В противном случае значение SOCKET_ERROR возвращается, и конкретный код ошибки может быть получен путем вызова WSAGetLastError.

WSAEINVAL
Сокет не был связан с bind

В вашем socketBind() метод, если socket() успешно, вы звоните return прежде чем позвонить bind()поэтому сокет никогда не привязан. Вы должны удалить return заявление в 1-м else блок. Кроме того, если bind() успешно, 2-й else блок зовет return перед звонком freeaddrinfo()так что вам нужно это исправить.

Попробуй это:

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

...
};
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]