select.select() 为什么不捕捉到套接字的异常情况?
我在用Python 2.7和Windows XP搭建一个服务器,这个服务器会给客户端发送消息。我使用了select模块来检查哪些socket准备好接收消息,同时也用它来捕捉一些特殊情况。我原以为如果客户端关闭了socket,select()会把这个socket放到特殊情况的列表里,但似乎并没有这样做:
lin, lout, lex = select.select(socklist, socklist, socklist)
for sock in lin:
# handle incoming messages
for sock in lout:
# send updates
for sock in lex:
# shut down server-side objects for particular client
那么,服务器要怎么判断客户端是否还连接着呢?因为服务器并不是一直在发送数据,所以我不想依赖socket.send()来测试客户端是否还在。
3 个回答
1
客户端关闭一个套接字并不是个例外情况。实际上,这种情况根本算不上例外。你会在异常条件的列表中看到各种错误,但一个正常关闭的套接字并不在其中。
3
在一个网络连接(也叫“套接字”)上,什么叫“异常情况”其实是跟底层的实现有关的。以Windows XP为例,它的底层实现是WinSock的选择功能,在这种情况下,异常情况包括:
- 如果你在处理一个连接请求(非阻塞模式),但是连接失败了。
- 有紧急数据可以读取。
8
一个关闭的套接字并不是一种异常(错误)情况。发生的事情是,这个套接字会在读取列表中(lin),当你尝试读取时,会得到0字节的数据。这意味着另一端已经关闭了这个套接字。
更新:
在正常情况下,你几乎不会在异常列表中看到任何东西,可以安全地忽略它。异常列表是用来处理一些很少用到的情况,比如带外数据(OOB)之类的。
对问题更新的回答:
可靠且快速地检测套接字的另一端是否已经断开连接可能会有点棘手。如果你需要可靠、及时地检测到这一点,那么你应该使用更高级的机制,比如保持连接(keepalive)或心跳(heartbeat)。
如果客户端正常关闭了套接字,那么你应该在读取列表中看到这个套接字。从套接字读取时会返回0字节,这表示套接字已经关闭(EOF)。