Как я могу убедиться, что клиент получил мое сообщение, используя UDP-сокеты в Python? - PullRequest
0 голосов
/ 17 октября 2019

Я пишу школьные упражнения с использованием UDP-сокетов в Python, и мне нужно обмениваться некоторой информацией (например, целочисленными значениями, строками и т. Д.) Между сервером и клиентом.

Я написал эту функцию, чтобы убедиться, чтосообщение, отправленное с сервера, получено на стороне клиента и наоборот:

import socket

BUFFER_SIZE = 1024

def send_udp_mgs(origin, destination, msg):
    msg = str(msg).encode('utf8')
    origin.sendto(msg, destination) # sending message
    # I never receive confirmation
    opt, _ = origin.recvfrom(BUFFER_SIZE) # Code stucks here
    opt = opt.decode('utf8')
    print(opt)

def receive_udp_msg(destination):
    msg, origin = destination.recvfrom(BUFFER_SIZE) # receiving message OK
    # This is the message sent as confirmation but is never received
    destination.sendto("CHECK".encode('utf8'), origin) # sent but not received
    msg = msg.decode()
    return msg

Я ожидаю, что код будет работать правильно с функцией, получающей подтверждение после отправки сообщения, но он застревает в ожидании подтверждения,Клиент отправляет подтверждение, но сервер никогда не получает его. Кроме этого, клиент получает сообщение хорошо, это только подтверждение обратно на сервер, который не удается.

Это код сервера:

def client_thread (s, c):
    print("Connection petition from", c)
    global n_cons
    cport = PORT + n_cons
    send_udp_mgs(s, c, cport)
    return

# UDP socket acting as server
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((IP, PORT))
while True:
    data, addr = s.recvfrom(BUFFER_SIZE)
    if data.decode() == CONNECT:
        n_cons += 1
        try:
            Thread(target=client_thread, args=(s,), kwargs={'c':addr}).start()
        except:
            print("Error creating thread")
            break

Код клиента

c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
c.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s = (IP, PORT)
# Connecting to the server
c.sendto(CONNECT.encode('utf8'), s)
cport = receive_udp_msg(c)

1 Ответ

0 голосов
/ 24 октября 2019

Я не смог заставить вашу программу остановиться в том месте, где, как вы сказали, она останавливается, но я смог найти проблему, которая, как я подозреваю, имеет аналогичную причину:

С более чем одним клиентомпоток, ожидающий подтверждения от одного клиента, может получить сообщение CONNECT от следующего клиента, а "основной цикл" сервера может получить сообщение с подтверждением.

Вы не можете избежать этой проблемы: если только выможет контролировать, когда все клиенты отправляют данные, вы не можете выделять потоки для разных клиентов, когда используете UDP. Я рекомендую использовать select, selectors или asyncio, или просто asyncio функции сокета длявыполняйте действия со своими сокетами.

Но вот еще кое-что, что следует учитывать: почему вы пытаетесь подтвердить UDP-сообщения? Если вам нужно убедиться, что другой конец соединения получает то, что вы отправляете, почему вы не используете TCP или какой-либо другой протокол, который имеет встроенные механизмы для обеспечения доставки?

Если вы действительно Чтобы использовать UDP, нужно , вам потребуется создать хотя бы одну структуру данных, чтобы отслеживать клиентов, которые пытаются «соединиться», и другую информацию об их «соединениях». Но UDP явно не требует соединения.


Как несвязанный комментарий, означает ли cport в client_thread, что вы планируете создать новый порт, в последовательном порядке , длякаждый клиент? Если это так, учтите, что (а) у вас может быть открыто только столько портов, (б) другой процесс может использовать один из этих портов, (в) если n_cons никогда не выйдет из строя, этот процесс будет использовать эти порты и (d) для чего вам нужно такое количество портов? (См. Также этот ответ .)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...