为什么我的 select() 不能接受新客户端?

Why is my select() cannot accept a new client ?

本文关键字:客户端 不能接受 我的 select 为什么      更新时间:2023-10-16

我正在做一个在Linux和Windows中运行的网络抽象。

要创建服务器套接字,我这样做:

int TCPSocket::create(unsigned int port)
{
_type = SERVER;
char *ip;
int error;
_sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (_sock == INVALID_SOCKET)
{
std::cerr <<"Winsock error - Socket creation Failed!n" << std::endl;
throw std::exception();
}
_sockAddr.sin_family = AF_INET;
_sockAddr.sin_port = htons(port);
hostent* thisHost;
thisHost = gethostbyname("");
ip = inet_ntoa (*(struct in_addr *)*thisHost->h_addr_list);
_sockAddr.sin_addr.s_addr = inet_addr(ip);
error = bind(_sock, (SOCKADDR *) &_sockAddr, sizeof(SOCKADDR));
if (error == SOCKET_ERROR)
{
std::cerr << "bind() failed with error:  " << WSAGetLastError() << std::endl;
closesocket(_sock);
WSACleanup();
throw std::exception();
}
error = listen(_sock, 1);
if (error == SOCKET_ERROR)
{
std::cerr << "listen() failed with error:  " << WSAGetLastError() << std::endl;
closesocket(_sock);
WSACleanup();
throw std::exception();
}
return _sock;
}

我把这个插座推到我的TCPSocket矢量中

error = WSAStartup(MAKEWORD(2,2), &_wsaData);
if (error)
{
std::cerr << "WSAStartup() failed with error:" << error << std::endl;
throw std::exception();
}
TCPSocket *servSock = new TCPSocket();
int fdCreated = servSock->create(_port);
_fdList.push_back(servSock);

然后我使用这种方式选择:

fd_set fd_read;
fd_set fd_write;
int fdMax;
int i = 0;
int selectRet;
FD_ZERO(&fd_read);
FD_ZERO(&fd_write);
fdMax = 0;
for (ISocket *tmpSock: _fdList)
{
TCPSocket *socket = reinterpret_cast<TCPSocket *>(tmpSock);
if (socket->getType() != TCPSocket::FREE)
{
FD_SET(socket->getSock(), &fd_read);
FD_SET(socket->getSock(), &fd_write);
fdMax = socket->getSock();
}
i++;
}
if ((selectRet = select(fdMax + 1, &fd_read, &fd_write, NULL, NULL)) == -1)
{
perror("select");
throw std::exception();
}
std::cout << "good" << std::endl;
std::cout << selectRet << std::endl;
if (selectRet > 0)
this->eventAction(fd_read, fd_write);

问题是,select()函数阻塞(我知道这是正常的),但是当我通过 windows telnet(telnet 本地主机端口)将客户端连接到服务器时the select()调用仍然没有返回任何内容。

这在 Unix 版本上运行良好。

我还注意到socket调用返回的文件描述符非常高,优于 250,正常吗?在 Unix 上,它总是返回一个低于 de 5 的文件描述符。

我相信您也可以将s_addr设置为零,以便它将套接字绑定到所有可用地址或显式htonl(0x7f000001)"127.0.0.1"。 "本地主机"的定义可能令人惊讶。 - D.肖利

@D.肖利 你是对的,我把s_addr设置为 0,这有效! – 迪米特里·达尼洛夫