我正在制作一个小型IRC服务器,但我遇到了一个问题;在尝试收听套接字时,我收到错误10022(无效参数)。
错误也出现在accept()上,但这是因为套接字没有监听(我发布的问题)。
我没有包含accept函数,因为我认为没有必要,并且会添加无意义的代码。
#include <iostream>
#include <ws2tcpip.h>
#include <winsock2.h>
#include <thread>
#include <string>
#pragma comment(lib, "Ws2_32.lib")
#define maxConnections 10
class Server
{
struct sockaddr_storage their_addr;
struct addrinfo hints, *res;
struct addrinfo *servinfo;
int status;
SOCKET sock;
public:
void Start(const char *port);
};
void Server::Start(const char *port)
{
WSADATA WSAData;
if (WSAStartup(MAKEWORD(2, 0), &WSAData) != 0)
{
std::cout << "[ERROR]: " << GetLastError() << ".\n";
}
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
status = getaddrinfo(NULL, port, &hints, &res);
sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sock == SOCKET_ERROR)
{
std::cout << "[ERROR]: " << WSAGetLastError() << "Bad Socket.\n";
}
bind(sock, res->ai_addr, res->ai_addrlen);
错误:
if (listen(sock, maxConnections) == SOCKET_ERROR)
{
std::cout << "[ERROR]: " << WSAGetLastError() << " Listening Failed.\n";
}
上面的代码详细介绍了套接字的创建和绑定,所有这些都是成功的(尽管不一定正确)。包含'NULL'的套接字创建可能是个问题。
谢谢:)
答案 0 :(得分:0)
我重读了我的代码并意识到我需要在这里添加一个支票
status = getaddrinfo(NULL, port, &hints, &res);
我把它改成了
if (status = getaddrinfo(NULL, port, &hints, &res) != 0)
{
std::cout << "[ERROR]: " << WSAGetLastError() << "Get Address Info failed.\n";
}
并且启动成功。
如果有人可以解释原因,我会改进我的答案。
答案 1 :(得分:0)
WSAStartup()
和getaddrinfo()
不使用(WSA)GetLastError()
,而是直接返回实际的错误代码。您没有在错误消息中考虑到这一点。
socket()
在失败时返回INVALID_SOCKET
,而不是SOCKET_ERROR
。
使用getaddrinfo()
创建侦听套接字时,应在AI_PASSIVE
参数的addrinfo.ai_flags
字段中指定hints
。这将使输出addrinfo
填充适合传递给bind()
的数据。
尝试更像这样的事情:
class Server
{
private:
bool winsockStarted;
SOCKET sock;
...
public:
Server();
~Server();
bool Start(const char *port);
void Stop();
...
};
Server::Server()
: sock(INVALID_SOCKET), winsockStarted(false)
{
WSADATA WSAData = {0};
int status = WSAStartup(MAKEWORD(2, 0), &WSAData);
if (status != 0)
std::cout << "[ERROR]: " << status << " Unable to start Winsock." << std::endl;
else
winsockStarted = true;
}
Server::~Server()
{
Stop();
if (winsockStarted)
WSACleanup();
}
bool Server::Start(const char *port)
{
Stop();
struct addrinfo hints = {0};
struct addrinfo *res = NULL;
hints.ai_flags = AI_PASSIVE;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
int status = getaddrinfo(NULL, port, &hints, &res);
if (status != 0)
{
std::cout << "[ERROR]: " << status << " Unable to get address info for Port " << port << "." << std::endl;
return false;
}
SOCKET newsock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (newsock == INVALID_SOCKET)
{
std::cout << "[ERROR]: " << WSAGetLastError() << " Unable to create Socket." << std::endl;
freeaddrinfo(res);
return false;
}
if (bind(newsock, res->ai_addr, res->ai_addrlen) == SOCKET_ERROR)
{
std::cout << "[ERROR]: " << WSAGetLastError() << " Unable to bind Socket." << std::endl;
freeaddrinfo(res);
closesocket(newsock);
return false;
}
freeaddrinfo(res);
if (listen(newsock, maxConnections) == SOCKET_ERROR)
{
std::cout << "[ERROR]: " << WSAGetLastError() << " Unable to Listen on Port " << port << "." << std::endl;
closesocket(newsock);
return false;
}
sock = newsock;
return true;
}
void Server::Stop()
{
if (sock != INVALID_SOCKET)
{
closesocket(sock);
sock = INVALID_SOCKET;
}
}