如何退出Python的TCP接受函数?

huangapple go评论107阅读模式
英文:

How to exit Python's tcp accept function?

问题

这个程序无法退出,因为accept函数会阻塞。

如果希望程序在超时后即使accept函数仍在运行时也能退出,可以进行以下操作:

  1. import socket
  2. import time
  3. HOST = "127.0.0.1" # 标准回环接口地址(本地主机)
  4. PORT = 65432 # 要监听的端口(非特权端口 > 1023)
  5. def connect():
  6. with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
  7. s.bind((HOST, PORT))
  8. print("监听中")
  9. s.listen()
  10. s.settimeout(5) # 设置超时时间为5秒
  11. print("等待连接")
  12. try:
  13. conn, addr = s.accept()
  14. except socket.timeout:
  15. print("超时,退出程序")
  16. return
  17. print(f"已连接 {addr}")
  18. with conn:
  19. while True:
  20. data = conn.recv(1024)
  21. if not data:
  22. break
  23. conn.sendall(data)
  24. def main():
  25. connect()
  26. if __name__ == "__main__":
  27. main()

上述代码使用settimeout函数来设置accept函数的超时时间,如果在5秒内没有连接到达,程序会超时退出。

英文:

This program cannot exit because the accept function blocks.

What can be done so that the program exits after a timeout even if the accept function is still running?

  1. # taken from https://realpython.com/python-sockets/#echo-server
  2. import socket
  3. HOST = "127.0.0.1" # Standard loopback interface address (localhost)
  4. PORT = 65432 # Port to listen on (non-privileged ports are > 1023)
  5. def connect ():
  6. with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
  7. s.bind((HOST, PORT))
  8. print("listening")
  9. s.listen()
  10. print("accepting")
  11. conn, addr = s.accept() # If these lines are
  12. with conn: # commented, the program
  13. print(f"Connected by {addr}") # exits normally.
  14. while True: # This is why I think
  15. data = conn.recv(1024) # that the *accept* function
  16. if not data: # is the problem
  17. break #
  18. conn.sendall(data) #
  19. def main():
  20. connect()
  21. if __name__ == "__main__":
  22. main()

答案1

得分: 1

你可以在服务器套接字上设置超时时间:

  1. >>> import socket
  2. >>> s=socket.socket()
  3. >>> s.bind(('',5000))
  4. >>> s.listen()
  5. >>> s.settimeout(5) # 5秒
  6. >>> s.accept() # 在这里等待...
  7. Traceback (most recent call last): # 5秒后...
  8. File "<stdin>", line 1, in <module>
  9. File "D:\dev\Python311\Lib\socket.py", line 294, in accept
  10. fd, addr = self._accept()
  11. ^^^^^^^^^^^^^^
  12. TimeoutError: 超时

如果要实现其他行为,可以捕获超时。例如:

  1. def accept(s):
  2. ''' 等待最多5秒的连接。'''
  3. s.settimeout(5)
  4. try:
  5. results = s.accept()
  6. except TimeoutError:
  7. return None
  8. s.settimeout(None) # 禁用超时
  9. return results
英文:

You can set a timeout on the server socket:

  1. >>> import socket
  2. >>> s=socket.socket()
  3. >>> s.bind(('',5000))
  4. >>> s.listen()
  5. >>> s.settimeout(5) # 5 seconds
  6. >>> s.accept() # waits here...
  7. Traceback (most recent call last): # 5 seconds later...
  8. File "<stdin>", line 1, in <module>
  9. File "D:\dev\Python311\Lib\socket.py", line 294, in accept
  10. fd, addr = self._accept()
  11. ^^^^^^^^^^^^^^
  12. TimeoutError: timed out

Catch time timeout if you want to implement other behavior. For example:

  1. def accept(s):
  2. ''' Wait up to 5 seconds for connection.'''
  3. s.settimeout(5)
  4. try:
  5. results = s.accept()
  6. except TimeoutError:
  7. return None
  8. s.settimeout(None) # disable timeout
  9. return results

huangapple
  • 本文由 发表于 2023年2月10日 13:41:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/75407363.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定