只关闭一个插座
Close only one socket
我制作了一个软件,它的作用就像套接字服务器(在基础设施中的三个节点之间调度数据包)。为了简单起见,我创建了三个线程,每个TCP套接字一个线程(我知道这不是最佳的,但就我的目的而言,这是最简单也是最快的选项),一切都很好。在服务器启动时,三个套接字执行通常的初始化(getaddr、listen、bind等),并侦听三个不同的端口;当我启动客户端时,客户端会正确连接并发送/recv数据。
问题是:每当一个客户端断开连接时,甚至其他套接字也会被强制断开连接并重新启动,这是一个问题。我敢打赌可疑代码就在这里(这是从线程启动的例程):
void ManageSocket1( void )
{
while( true )
{
Socket* socket = new Socket( 27016, "SocketName" );
if( socket->CreateSocket() )
{
socket->StartCommunication();
}
socket->CloseSocket();
delete socket;
}
}
void ManageSocket2( void )
{
// clone of ManageSocket1
}
CreateSocket()负责套接字的创建,而StartCommunication()负责接收/发送数据;对于这两种方法,不需要发布代码,因为这是一个"常见"的tcp套接字打开代码。ManageSocketX()是由main()中的线程启动的,由于其性质,永远不会返回到main()。
这就是CreateSocket():
int Socket::CreateSocket( void )
{
res = WSAStartup( MAKEWORD( 2,2 ), &wsaData );
if( res != 0 )
{
logBook->PrintMsg( socketName, "WSAStartup failed" );
return ERROR;
}
else
{
logBook->PrintMsg( socketName, "WSAStartup done" );
}
res = getaddrinfo( NULL, socketPort, &hints, &result );
if ( res != 0 )
{
logBook->PrintMsg( socketName, "GetAddrInfo failed" );
WSACleanup();
return ERROR;
}
else
{
logBook->PrintMsg( socketName, "GetAddrInfo succesful");
}
ListenSocket = socket( result->ai_family, result->ai_socktype, result->ai_protocol );
if( ListenSocket == INVALID_SOCKET )
{
logBook->PrintMsg( socketName, "GetAddrInfo failed with error: ", WSAGetLastError() );
freeaddrinfo( result );
WSACleanup();
return ERROR;
}
else
{
logBook->PrintMsg( socketName, "Socket created succesfully");
}
res = bind( ListenSocket, result->ai_addr, ( int )result->ai_addrlen );
if( res == SOCKET_ERROR )
{
logBook->PrintMsg( socketName, "Bind failed with error: ", WSAGetLastError() );
freeaddrinfo( result );
closesocket( ListenSocket );
WSACleanup();
return ERROR;
}
else
{
logBook->PrintMsg( socketName, "Socket successfully bound");
}
freeaddrinfo( result );
if( listen( ListenSocket, SOMAXCONN ) == SOCKET_ERROR )
{
logBook->PrintMsg( socketName, "Bind failed with error: ", WSAGetLastError() );
closesocket( ListenSocket );
WSACleanup();
return ERROR;
}
else
{
logBook->PrintMsg( socketName, "Listening on port", atoi( socketPort ) );
}
ClientSocket = accept( ListenSocket, NULL, NULL );
if( ClientSocket == INVALID_SOCKET )
{
logBook->PrintMsg( socketName, "Accept failed:", WSAGetLastError() );
closesocket( ListenSocket );
WSACleanup();
return 1;
}
else
{
logBook->PrintMsg( socketName, "Client connection accepted" );
}
return SUCCESS;
}
这就是StartCom()
void Socket::StartCommunication( void )
{
char recvbuf[BUFLEN];
int recvbuflen = BUFLEN;
do
{
res = recv( ClientSocket, recvbuf, recvbuflen, 0 );
if( res > 0 )
{
logBook->PrintMsg( socketName, "Bytes received:", res );
}
else if( res == 0 )
{
logBook->PrintMsg( socketName, "Connection closing..." );
}
else
{
logBook->PrintMsg( socketName, "Receive failed:", WSAGetLastError() );
closesocket( ClientSocket );
WSACleanup();
return;
}
}
while( res > 0 );
}
问题是,当任何套接字终止时,您正在调用WSACleanup
。来自文件:
在多线程环境中,WSACleanup终止所有线程的Windows套接字操作。
进一步:
调用WSACleanup时打开的套接字将重置并自动解除分配,就像调用closesocket一样。
相关文章:
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 运行同一解决方案的另一个项目的项目
- 挂起和取消挂起一个文件DLL
- 用C++中的一个变量定义一个常量
- 函数向量_指针有不同的原型,我可以构建一个吗
- 在c++中用vector填充一个简单的动态数组
- 如何在选项卡视图Qt中设置一个新项目,并保存以前的项目
- 预处理器:插入结构名称中的前一个行号
- 我在c++代码中生成了一个运行时#3异常
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 从链接列表c++中删除一个项目
- 告诉一个 const char 数组,除了编译时 C 样式的字符串外,它不以 '