gpt4 book ai didi

C++ Socket select() before accept() 多次看到相同的连接

转载 作者:行者123 更新时间:2023-11-28 02:11:23 28 4
gpt4 key购买 nike

我有一个监听函数,它检查是否有新连接在服务器套接字上等待,如果我先启动客户端然后启动服务器,我会多次看到“新连接”,如果我启动服务器并然后客户端我看到它一次。

我是否遗漏了一些 Posix 标准的知识或只是缺乏知识(最有可能)?

轮询新连接的函数是:

bool IPV4Socket::HasNewConnection( TimeoutValue *timeout )
{
SocketSet read_fd_set;
bool hasConnection = false;

SocketSet_ZERO( &read_fd_set );
SocketSet_SET( m_socket, &read_fd_set );

if ( m_socketAdaptor->select( m_socket + 1
, &read_fd_set
, NULL
, NULL
, timeout ) < 0 )
{
throw( std::string( "::select() failed, unable to continue." ) );
}

for ( unsigned int i = 0; i <= m_socket; i++ )
{
if ( m_socketAdaptor->SocketSet_ISSET( i, &read_fd_set ) &&
( i == m_socket ) )
{
hasConnection = true;
}
}

return hasConnection;
}

它被称为使用:

while( 1 )
{
if ( socket->HasNewConnection( &newConnTimeout ) )
{
std::cout << "[INFO] A new connection is waiting...." << std::endl;

acceptedSocket = socket->Accept( &newConnTimeout );

if ( acceptedSocket )
{
std::cout << "[INFO] New connection received...." << std::endl;
}
}
}

连接功能是:

while( connStatus == false )
{
socket = socketlayer->CreateSocket( socketlayer::SockType_stream );

socket->SetNonBlocking( true );
socket->SetSocketOption( socketlayer::SocketOption_KeepAlive, true );
socket->SetSocketOption( socketlayer::SocketOption_ReuseAddr, true );

connStatus = socket->Connect( "127.0.0.1", 18000, &tv );

if ( connStatus == false ) socket->Close();
}

由于这是一段开源代码,可以在 Sourceforge 中找到

连接是通过:

bool IPV4Socket::Connect( std::string hostname
, unsigned short remotePort
, TimeoutValue *timeout )
{
AddrInfo getResults;
AddrInfo getaddrinfoHints;
int connReturn = 0;
SockAddr_In *addrData;
//bool connectSuccess = false;
std::string service = std::to_string( remotePort );

getaddrinfoHints.ai_family = AddressFamily_inet;
getaddrinfoHints.ai_socktype = SockType_stream;

if ( m_socketAdaptor->getaddrinfo( hostname
, service
, &getaddrinfoHints
, &getResults ) != 0 )
{
return false;
}

addrData = (SockAddr_In *)&( *getResults.ai_addr.begin() );

connReturn = m_socketAdaptor->connect( m_socket
, (const Sockaddr *)addrData
, (int)getResults.ai_addrlen );

if ( connReturn == SocketError)
{
int m_lastErrorCode = m_socketAdaptor->GetLastError();

// Connection error : FATAL
if ( ( m_lastErrorCode != SockErr_EWOULDBLOCK) &&
( m_lastErrorCode != SockErr_EALREADY ) &&
( m_lastErrorCode != SockErr_EINPROGRESS ) )
{
return false;
}
}

SocketSet writeFDS;
//SocketSet exceptFDS;
int selectReturn = 0;

// Clear all the socket FDS structures
SocketSet_ZERO( &writeFDS );
//SocketSet_ZERO( &exceptFDS );

// Put the socket into the FDS structures
SocketSet_SET( m_socket, &writeFDS );
//SocketSet_SET( m_socket, &exceptFDS );

selectReturn = m_socketAdaptor->select( m_socket + 1
, NULL
, &writeFDS
, NULL
, timeout );

// Check for Socket Error or timeout
if ( ( selectReturn == SocketError ) || ( selectReturn == 0 ) )
{
return false;
}

return true;
}

最佳答案

套接字设置为非阻塞,并调用connect通常会返回一个错误,因为连接状态还不能确定:

With a nonblocking socket, the connection attempt cannot be completed immediately. In this case, connect will return SOCKET_ERROR, and WSAGetLastError will return WSAEWOULDBLOCK. (...)

  • Use the select function to determine the completion of the connection request by checking to see if the socket is writeable.

鉴于您的客户端代码和上述文档,它应该永远无法成功连接。但是,由于您使用环回设备进行连接,因此在您的服务器已经在运行的情况下,由于计时的原因,连接可能(并且确实)会立即被接受。

因此,要么如上所述在 connect 调用之后在客户端上使用 select,要么只使用阻塞套接字。

关于C++ Socket select() before accept() 多次看到相同的连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35559434/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com