我知道“通过对等方重置连接”意味着什么,可能这已经得到了解答,但是我找不到对不起。
我正在使用TCP创建一个客户端和服务器,并且服务器应该是24/7,当它关闭时,但是当我关闭客户端时,发送和recv由于'由peer重置连接'而失败。好吧,但问题是服务器完全挂起,只允许客户端连接,不与send / recv通信,我不假装总是重新启动服务器。
这是我正在使用的源代码:
客户端:
bool Browsify::Connect( const char* addr, unsigned short port )
{
if(!net.isInitialized)
{
Log::Error( "Browsify wasn't initialized." );
return false;
}
net.addr = addr;
net.port = port;
net.s = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if(res == INVALID_SOCKET)
{
Log::Error( "socket() failed - %d.", WSAGetLastError() );
return false;
}
sockaddr_in sk;
memset( (char*) &sk, 0, sizeof(sk) );
sk.sin_addr.s_addr = inet_addr( addr );
sk.sin_port = htons( port );
sk.sin_family = AF_INET;
res = connect( net.s, (sockaddr*) &sk, sizeof(sk) );
if(res == SOCKET_ERROR)
{
Log::Error( "connect() failed - %d.", WSAGetLastError() );
return false;
}
net.isConnected = true;
CreateThread( NULL, NULL, (LPTHREAD_START_ROUTINE)
Browsify::HandleReceive, NULL, NULL, NULL );
return true;
}
ServerItem item[1024];
bool Browsify::HandleReceive()
{
char buf[512];
sprintf( buf, "getservers iw4" );
res = send( net.s, buf, sizeof(buf), NULL );
if(res == SOCKET_ERROR)
{
Log::Error( "send() failed - %d.", WSAGetLastError() );
return false;
}
res = recv( net.s, (char*)&item, sizeof(item), NULL );
if(res == SOCKET_ERROR)
{
Log::Error( "recv() failed - %d.", WSAGetLastError() );
return false;
}
while(true)
{
if(res > NULL)
{
Browsify::QueryServer( 0 );
// finally.. after thousands and thousands of years, I did it!
// no winsock error, though, the server is really unstable.
//Log::Info( "server count %d", item->serverCount );
}
else if(res == NULL)
{
Log::Warning( "Connection closed." );
}
Sleep( 1 );
}
return true;
}
服务器
bool Browsify::Listen( uint16 port )
{
printf( "# Listening on port %u...\n", port );
if(!net.isInitialized)
{
printf( "ERROR: Browsify wasn't initialized.\n" );
return false;
}
net.port = port;
net.sListen = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if(net.sListen == INVALID_SOCKET)
{
printf( "ERROR: socket() failed - %d.\n", WSAGetLastError() );
return false;
}
sockaddr_in sk;
memset( (char*) &sk, 0, sizeof(sk) );
sk.sin_addr.s_addr = ADDR_ANY;
sk.sin_port = htons( port );
sk.sin_family = AF_INET;
res = bind( net.sListen, (sockaddr*) &sk, sizeof(sk) );
if(res == SOCKET_ERROR)
{
printf( "ERROR: bind() failed - %d.\n", WSAGetLastError() );
return false;
}
res = listen( net.sListen, SOMAXCONN );
if(res == SOCKET_ERROR)
{
printf( "ERROR: listen() failed - %d\n", WSAGetLastError() );
return false;
}
net.sClient = accept( net.sListen, NULL, NULL );
if(net.sClient == INVALID_SOCKET)
{
printf( "ERROR: accept() failed - %d\n", WSAGetLastError() );
return false;
}
else
{
printf( "# Unknown connection accepted.\n" );
}
closesocket( net.sListen );
net.isListening = true;
CreateThread( NULL, NULL, (LPTHREAD_START_ROUTINE)
Browsify::HandleReceive, NULL, NULL, NULL );
return true;
}
bool Browsify::HandleReceive()
{
char recvbuf[1024];
res = recv( net.sClient, recvbuf, sizeof(recvbuf), NULL );
if(res == SOCKET_ERROR)
{
printf( "ERROR: recv() failed - %d.\n", WSAGetLastError() );
closesocket( net.sClient );
WSACleanup();
//return false;
}
while(true)
{
if(res > NULL)
{
if(!strcmp( recvbuf, "getservers iw4" ))
{
ServerItem item[1024];
strcpy( item[0].hostname, "^1PLAY^34^1FUN ^2TDM" );
strcpy( item[0].mapname, "mp_rust" );
strcpy( item[0].gametype, "war" );
strcpy( item[0].addr, "127.0.0.1" );
item[0].currPlayers = 1;
item[0].maxPlayers = 18;
item[0].port = 27005;
strcpy( item[1].hostname, "^1PLAY^34^1FUN ^2ISNIPE" );
strcpy( item[1].mapname, "mp_terminal" );
strcpy( item[1].gametype, "iSnipe" );
strcpy( item[1].addr, "127.0.0.1" );
item[1].currPlayers = 15;
item[1].maxPlayers = 18;
item[1].port = 27005;
item->serverCount = 2;
res = send( net.sClient, (char*) &item, sizeof(item), NULL );
if(res == SOCKET_ERROR)
{
printf( "send() failed - %d\n", WSAGetLastError() );
closesocket( net.sClient );
WSACleanup();
//return false;
}
}
}
else if(res == NULL)
{
printf( "Connection closed.\n" );
}
Sleep( 1 );
}
shutdown( net.sClient, SD_SEND );
return true;
}
这就是游戏的服务器浏览器,这就是为什么它应该是24/7。
答案 0 :(得分:0)
我认为问题在于您多次呼叫listen()
。这不是服务器被禁止工作的方式。
进入服务器的正确方法是(伪代码):
SOCKET one_time_initialization()
{
SOCKET listenSocket = socket(...);
bind(listenSocket, ...);
listen(listenSocket, ...);
return listenSocket; //do not close the listensocket until the finishes!
}
void accept_connections(SOCKET listenSocket)
{
for (;;) //or message driven, that depends on the application architecture
{
SOCKET socket = accept(listenSocket);
//you should really create a structure/object here, add the socket in there
//and create a thread passing the pointer to that structure as `lParam`
Connection *data = new Connection(socket);
CreateThread(NULL, NULL, HandleReceive, NULL, NULL, data);
//the socket should be closed when the thread finishes and the data is deleted
}
}