Получение ConnectionResetError при остановке клиентского скрипта на UDP-сокете - PullRequest
2 голосов
/ 05 августа 2020
• 1000 блок try и 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


сценарий затем использует sock.sendto () для каждого адреса в списке listeners

Клиент:

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
    

Ответы [ 2 ]

1 голос
/ 06 августа 2020

Я считаю, что вы ищете socket.getpeername().

Это вернет удаленный адрес, к которому подключен сокет.

Ваш подход к обработке данных в проводе, когда соединение закрыто / потеряно, является правильным. Обработка с помощью try/catch или методов recv() или recvfrom() для ожидания ответа перед закрытием сокета.

0 голосов
/ 06 августа 2020

С тех пор, как я разместил это, я обнаружил, что это фактически TCP, и это не сработает для проекта, который я пытаюсь сделать. Приветствуются любые дополнительные указания и помощь, я не могу найти никаких примеров Multiclient UDP-серверов, которые работают через один сокет.

Я частично решил свою систему после использования Пример , предоставленный AztCrw4282. Мне удалось найти решение, я вместо этого использовал socket.accept() aproach, я не уверен, 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))
...