Bra*_*ner 5 c++ sockets linux blocking
我有一个侦听新连接的线程
new_fd = accept(Listen_fd, (struct sockaddr *) & their_addr, &sin_size);
Run Code Online (Sandbox Code Playgroud)
和另一个在关闭程序时关闭Listen_fd的线程.然而,在Listen_fd关闭后,它仍然会阻塞.当我使用GDB尝试和调试时,accept()不会阻塞.我认为这可能是SO_LINGER的问题,但默认情况下它不应该打开,并且在使用GDB时不应该更改.有什么想法,或关闭列表套接字的任何其他建议?
accept调用不是有效套接字FD的东西时的行为是未定义的."不是有效的套接字FD"包括曾经是有效套接字但后来被关闭的数字.您可能会说"但Borealid,它应该返回EINVAL!",但这并不能保证 - 例如,相同的FD号码可能会重新分配给您close和accept呼叫之间的不同套接字.
因此,即使您要隔离并纠正使程序失败的任何原因,您将来仍可能再次失败.不要这样做 - 纠正导致您尝试accept在已关闭的套接字上建立连接的错误.
如果你的意思是之前做过的呼叫accept 继续阻塞close,那么你应该做的是向阻塞的线程发送一个信号accept.这将使它EINTR并且它可以干净地脱离 - 然后关闭插座.请勿从使用它的线程以外的线程中关闭它.
使用: sock.shutdown (socket.SHUT_RD)
然后accept将返回EINVAL。无需丑陋的交叉螺纹信号!
在Python文档中:“ Note close()释放与连接关联的资源,但不一定立即关闭连接。如果要及时关闭连接,请shutdown()在之前调用close()。”
http://docs.python.org/3/library/socket.html#socket.socket.close
几年前,我在用C语言编程时遇到了这个问题。但是,直到在Python中遇到相同的问题,并思考使用信号(糟糕!)之后,我才找到了解决方案,然后记住了有关shutdown!
至于说不应该关闭/使用线程间套接字的注释……在CPython中,全局解释器锁应该为您提供保护(假设您使用的是文件对象,而不是原始的整数文件描述符)。
这是示例代码:
import socket, threading, time
sock = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind (('', 8000))
sock.listen (5)
def child ():
print ('child accept ...')
try: sock.accept ()
except OSError as exc : print ('child exception %s' % exc)
print ('child exit')
threading.Thread ( target = child ).start ()
time.sleep (1)
print ('main shutdown')
sock.shutdown (socket.SHUT_RD)
time.sleep (1)
print ('main close')
sock.close ()
time.sleep (1)
print ('main exit')
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9182 次 |
| 最近记录: |