我有一个服务器应用程序 .
服务器正在尝试从线程中的客户端连接:
while( (client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) )
{
.....
}
我有另一个在我的应用程序的退出中执行的线程 . 在这个线程中我关闭套接字 socket_desc
:
close(socket_desc);
在线程中关闭套接字的风险是什么,还有另一个线程在同一个套接字上接受?
3 回答
据我所知,您描述的操作组合的语义没有定义,这应该足以让您找到替代方案 . 我推测合理可能观察到的行为包括
close()
快速返回,并且accept()
调用快速失败,可能表示EBADF
,EINVAL
或ENOTSOCK
错误,或者accept()
呼叫继续阻止,直到连接请求到达,或accept()
无限期地阻止呼叫;要么close()
阻止,直到accept()
返回,如果有的话;要么close()
和accept()
死锁 .但是,如果确实没有定义语义,那么几乎任何事情都可能发生 .
如果一个不同的线程必须关闭套接字而不是它上面的一个连接,那么你应该明智地设置某种标志来指示程序正在退出,然后
accept()
accept()
ing线程将其从accept()
中分离出来 . 接收到这种信号的线程将从程序退出标志知道停止而不是再次尝试accept()
.如果您的线程可以取消,那么全局标志可以采用线程取消消息的形式 .
accept()
函数是取消点,因此您的线程将在下次调用accept()
之前收到取消消息 .我错了 . 但是,它可能适用于这样的场景: - 考虑3个线程 - A,B,C .
线程A等待套接字并进入休眠状态
线程B关闭套接字
线程C创建一个新的套接字,它恰好获得与最近关闭的套接字相同的文件描述符编号(套接字也是一个文件)
线程A唤醒(
accept
上有错误代码),然后调用close
认为意外错误=>这会影响在C中创建的完全不同的有效套接字!!您可以关闭套接字以中止accept函数 . 但是您必须更改代码,并仔细检查API函数的返回值 . while循环中的尝试不起作用,因为它不检查SOCK_ERROR(-1) .