【问题标题】:Getting a ConnectionResetError when client script is stopped on UDP socket当客户端脚本在 UDP 套接字上停止时获取 ConnectionResetError
【发布时间】:2020-11-25 21:42:36
【问题描述】:

我正在制作一个脚本,允许多个客户端查看来自服务器脚本的实时摄像机镜头,这一切正常,直到其中一个客户端脚本关闭,然后引发 ConnectionResetError,为避免这种情况,我使用了尝试和 except 块来捕获 ConnectionResetError 但每次连接丢失后都会引发相同的错误。仅使用socket.recv 会停止ConnectionResetError,但socket.recv 不会返回脚本将视频流发送回客户端所需的发件人地址。

服务器:

host = "0.0.0.0"
port = 5000
buffer_size = 1024

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("", port))

listeners = list()  # the addresses of the clients that want the video stream

def handle_queue(sock):
    while True:
        try:
            message, address = sock.recvfrom(buffer_size)  # block the thread until a packet arrives
            print(address)
            message = str(message, "utf-8")  # decode the message
            if message == "join":
                listeners.append(address)  # add the list of listeners
            else:
                print("unknown queue msg: ", message)
        except ConnectionResetError:
            print("The connection was forcefully quit")
        

queue_handler_thread = Thread(target=handle_queue, args=(sock,), daemon=True)
queue_handler_thread.start()  # start the queue


脚本然后对listeners 列表中的每个地址使用 sock.sendto()

客户:

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

sock.sendto(bytes("join","utf-8"), (host, port))

while True:
    data, address = sock.recvfrom(max_length)  # block main thread until a packet is received
    

【问题讨论】:

    标签: python python-3.x sockets networking udp


    【解决方案1】:

    我相信您正在寻找的是socket.getpeername()

    这将返回套接字连接的远程地址。

    您在连接关闭/丢失时处理线路中的数据的方法是正确的方法。通过try/catch 处理或使用recv()recvfrom() 方法在关闭套接字之前等待响应。

    【讨论】:

    • 会不会是我通过一个套接字与多个客户端通信?因为一旦一个客户端断开连接,每次代码循环都会抛出错误,解决这个问题的唯一方法是关闭套接字,但是我无法与仍然连接的所有其他客户端通信。
    • 老实说,我不确定这一点,因为我已经有一段时间没有使用套接字了,但我确信一个套接字可以处理多个连接。您可以查看this,了解如何打开多个套接字连接并查看是否修复。抛出错误时,您是否也可以不断开客户端连接,即从服务器中删除他们的address?另见this 为例
    • 不幸的是那个例子是 TCP
    【解决方案2】:

    自从发布此消息后,我发现它实际上是 TCP,这对我正在尝试做的项目不起作用。任何更多的指导和帮助将不胜感激,我似乎找不到任何通过一个套接字运行的多客户端 UDP 服务器的示例。

    在使用 AztCrw4282 提供的 Example 后,我部分解决了我的系统。 我能够找到解决方案,我改为使用socket.accept() 方法,我不确定这是 UDP 还是 TCP(我想要 UDP,但对于连接系统,我认为这是 TCP 的握手,但我不是100% 确定),但它现在有效。

    客户端必须连接到服务器,然后服务器将接受或拒绝连接,接受后将创建一个线程来管理该客户端连接。如果在与该客户端交互时抛出任何错误,它们的连接将被关闭。

    服务器

    try:
        ServerSocket.bind((host, port))
    except socket.error as e:
        print(str(e))
    
    print('Waiting for a Connection..')
    ServerSocket.listen(5)
    
    connections = list()
    
    def threaded_client(connection):
        connection.send(str.encode('Welcome to the Server\n'))
        while True:
            try:
                data = str(connection.recv(2048),"utf-8")  # this needs to be try catched
                print("Packet Recv: ", data)
                if data == "join":
                    print("Client Joined")
                if data == "quit":
                    break
                if not data:
                    break
            except ConnectionResetError:
                break
        print("Closing a connection")  # need to handle leaving the stream
        connection.close()
    
    def handle_stream():
        for connection in connections:
            try:
                connection.send(bytes(json.dumps(frame_info) ,"utf-8"))
            except:
                print("Packet send failure, kicking client")
                connections.remove(connection)
    
    while True:
        Client, address = ServerSocket.accept()
        print('Connected to: ' + address[0] + ':' + str(address[1]))
        connections.append(Client)
        Thread(target=threaded_client, args=(Client, ), daemon=True).start()
        ThreadCount += 1
        print('Thread Number: ' + str(ThreadCount))
    

    客户端唯一改变的部分是它连接到服务器的部分

    try:
        ClientSocket.connect((host, port))
    except socket.error as e:
        print(str(e))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-16
      • 2020-07-22
      • 2011-08-15
      • 2014-11-19
      • 2021-04-09
      • 1970-01-01
      • 2018-05-23
      相关资源
      最近更新 更多