这是我在这个伟大网站上的第一个问题。
我正在编写一个简单的服务器,从用户那里获取端口号:
#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,我看不到传递给函数的无效参数。
答案 0 :(得分:1)
错误代码10022是WSAEINVAL
:
参数无效。
提供了一些无效参数(例如,为setsockopt
函数指定无效级别)。 在某些情况下,它还引用套接字的当前状态 - 例如,在未侦听的套接字上调用accept
。
返回值
如果没有错误发生,
listen
将返回零。否则,返回SOCKET_ERROR
的值,并且可以通过调用WSAGetLastError
来检索特定的错误代码。...
<强> WSAEINVAL 强>
绑定
套接字尚未与bind
在socketBind()
方法中,如果socket()
成功,则在调用return
之前调用bind()
,因此套接字永远不会绑定。您需要删除第一个return
块中的else
语句。此外,如果bind()
成功,则第二个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");
}
...
};