【发布时间】:2012-06-14 23:22:06
【问题描述】:
我正在尝试在指定时间段后让我的接受呼叫超时,并尝试按照此处的建议进行操作:
在这种情况下,我在调用它时传递了一个 TIMEVAL 结构来选择,问题是当我将 tv.tv_usec 设置为大约 40 分钟左右时,选择调用立即超时,而不是等待我指定的 40 分钟。 MSDN 声明 select 的超时是它将等待的最长时间,我如何使 select 或 accept 等待特定的时间段,然后超时?
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <WinSock2.h>
#include <Ws2tcpip.h>
#include <cstdio>
#include <tchar.h>
VOID _tmain( int argc, TCHAR *argv[] )
{
WSADATA wsaData = { 0 };
ADDRINFOA hINTs = { 0 };
PADDRINFOA pResult = NULL;
SOCKET hServerSocket = INVALID_SOCKET,
hClientSocket = INVALID_SOCKET;
TIMEVAL tv = { 0 };
INT iReturnStatus = -1;
DWORD dwRecvTimeout = 30000, // Milliseconds
dwSendTimeout = 30000; // Milliseconds
fd_set readFDs = { 0 };
if ( WSAStartup( MAKEWORD( 2, 2 ), &wsaData ) )
{
_tprintf_s( TEXT( "WSAStartup Failed\n" ) );
return;
}
ZeroMemory( &hINTs, sizeof( hINTs ) );
hINTs.ai_family = AF_INET;
hINTs.ai_socktype = SOCK_STREAM;
hINTs.ai_protocol = IPPROTO_TCP;
hINTs.ai_flags = AI_PASSIVE;
if ( getaddrinfo( NULL, TEXT( "9001" ), &hINTs, &pResult ) )
{
WSACleanup();
_tprintf_s( TEXT( "getaddrinfo Failed\n" ) );
return;
}
if ( ( hServerSocket = socket( pResult -> ai_family, pResult -> ai_socktype, pResult -> ai_protocol ) ) == INVALID_SOCKET )
{
freeaddrinfo( pResult );
WSACleanup();
_tprintf_s( TEXT( "socket Failed\n" ) );
return;
}
int iResult = bind( hServerSocket, ( pResult -> ai_addr ), pResult -> ai_addrlen );
if ( iResult == SOCKET_ERROR )
{
freeaddrinfo( pResult );
closesocket( hServerSocket );
WSACleanup();
_tprintf_s( TEXT( "bind Failed\n" ) );
return;
}
freeaddrinfo( pResult );
if ( listen( hServerSocket, SOMAXCONN ) )
{
closesocket( hServerSocket );
WSACleanup();
_tprintf_s( TEXT( "listen Failed\n" ) );
return;
}
hClientSocket = INVALID_SOCKET;
for ( ;; )
{
tv.tv_usec = 2400000000; // microseconds
FD_ZERO( &readFDs );
FD_SET( hServerSocket, &readFDs );
_tprintf( "select()\n" );
iReturnStatus = select( 0, &readFDs, NULL, NULL, &tv );
// Select Error
if ( iReturnStatus == SOCKET_ERROR )
{
_tprintf( "select Failed\n" );
}
// Select Success
else if ( iReturnStatus )
{
// Connection Established On Server Socket
if ( FD_ISSET( hServerSocket, &readFDs ) )
{
// Accept Client Connection
hClientSocket = accept( hServerSocket, NULL, NULL );
if ( hClientSocket == INVALID_SOCKET )
{
_tprintf( "accept Failed\n" );
}
else
{
// Set Recv Timeout
setsockopt( hClientSocket, SOL_SOCKET, SO_RCVTIMEO, ( const char * ) &dwRecvTimeout, sizeof( dwRecvTimeout ) );
// Set Send Timeout
setsockopt( hClientSocket, SOL_SOCKET, SO_SNDTIMEO, ( const char * ) &dwSendTimeout, sizeof( dwSendTimeout ) );
// Process Client Request(s)
// HandleConnection( ClientSocket );
}
}
// Connection Established On Unknown Socket
else
{
_tprintf( "Invalid Socket Returned\n" );
}
}
// Select Timeout
else
{
_tprintf( "select Timeout\n" );
}
}
if ( hServerSocket != INVALID_SOCKET )
closesocket( hServerSocket );
return;
}
【问题讨论】:
-
MSDN 说最大时间,因为如果套接字在接受时不会阻塞,
select等待就会结束。因此,要么您的选择调用不正确,要么侦听套接字上有可用的连接。如果您发布一些代码,可能会对您有所帮助。 -
Checkout,是以秒或分钟为单位指定的超时时间。我认为它必须在几秒钟内而不是在几分钟内。
-
tv.tv_usec是微秒,tv.tv_sec是秒。另外,请显示您用于初始化结构/fd_sets 和select调用的代码。 -
因为你使用 tv_sec 的超时时间 GREATER 小于 1 秒,tv_usec 的超时时间 LESS 小于 1 秒,你应该 NOT i> 允许 tv_usec > 1,000,000。
-
tv.tv_sec = ( timeout_in_microseconds / 1000000 ); tv.tv_usec = ( timeout_in_microseconds % 1000000 );
标签: c++ c windows winapi winsock