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

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

How to exit Python's tcp accept function?

问题

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

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

import socket
import time

HOST = "127.0.0.1"  # 标准回环接口地址(本地主机)
PORT = 65432  # 要监听的端口(非特权端口 > 1023)

def connect():
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        print("监听中")
        s.listen()
        s.settimeout(5)  # 设置超时时间为5秒
        print("等待连接")
        try:
            conn, addr = s.accept()
        except socket.timeout:
            print("超时,退出程序")
            return
        print(f"已连接 {addr}")
        with conn:
            while True:
                data = conn.recv(1024)
                if not data:
                    break
                conn.sendall(data)

def main():
    connect()

if __name__ == "__main__":
    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?

# taken from https://realpython.com/python-sockets/#echo-server

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

def connect ():
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        print("listening")
        s.listen()
        print("accepting")
        conn, addr = s.accept()             # If these lines are 
        with conn:                          # commented, the program
            print(f"Connected by {addr}")   # exits normally.
            while True:                     # This is why I think
                data = conn.recv(1024)      # that the *accept* function
                if not data:                # is the problem
                    break                   #
                conn.sendall(data)          #

def main():
    connect()

if __name__ == "__main__":
    main()

答案1

得分: 1

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

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

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

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

You can set a timeout on the server socket:

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

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

def accept(s):
    ''' Wait up to 5 seconds for connection.'''
    s.settimeout(5)
    try:
        results = s.accept()
    except TimeoutError:
        return None
    s.settimeout(None)  # disable timeout
    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:

确定