Python-сокет, принимающий несколько сообщений одновременно - PullRequest
0 голосов
/ 29 марта 2019

Я делаю чат TCP / IP с python (3) сокетами, и у меня возникла та же проблема с несколькими экземплярами пар socket.send / socket.receive. Как пример:

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

Часто, хотя и не всегда, либо имена клиентов, либо строковые сигналы, либо оба смешиваются, как одно сообщение. Если у меня есть клиенты C1, C2, C3 и я посылаю сигнал «over», чтобы сказать, что список готов, мой список может отображать что-то вроде:

C1C2
C3
"Над"

Поскольку на стороне клиента есть только этот поток и поток GUI / Main, а на стороне сервера никакие другие типы сообщений не перепутаны (в потоках для прослушивания, обработки клиентов и GUI / Main), я предполагаю, что это не так. т проблема синхронизации. Я попытался добавить функции time.sleep () различного размера между сигналами и списком, но это все еще происходит.

Я замечал это на протяжении всего моего опыта с этим сокетным чатом, но смог найти исправления (обычно с помощью sleep ()), но этот меня озадачил. Я делаю что-то в корне неправильно, что портит мою отправку и получение сообщений? Как я могу гарантировать, что в каждый socket.send () будет отправляться один фрагмент данных?

1 Ответ

1 голос
/ 29 марта 2019

TCP - это протокол потока байтов.Нет никаких сообщений, а только входящие байты. Вы должны реализовать протокол и буферизовать полученные данные, пока не узнаете, что получили полное сообщение.

Вы можете использовать встроенный метод socket.makefile() дляреализовать линейно-ориентированный протокол.Пример:

server.py

from socket import *

s = socket()
s.bind(('',5000))
s.listen(1)

while True:
    c,a = s.accept()
    print(f'connect: {a}')
    read  = c.makefile('r')
    write = c.makefile('w')

    with c,read,write:
        while True:
            data = read.readline()
            if not data: break
            cmd = data.strip()
            print(f'cmd: {cmd}')
            if cmd == 'LIST':
                write.write('C1\nC2\nC3\nDONE\n')
                write.flush()

    print(f'disconnect: {a}')

client.py

from socket import *

s = socket()
s.connect(('localhost',5000))
read = s.makefile('r',)
write = s.makefile('w')

def send(cmd):
    print(cmd)
    write.write(cmd + '\n')
    write.flush()

with s,read,write:
    send('TEST')
    send('LIST')
    while True:
        data = read.readline()
        if not data: break
        item = data.strip()
        if item == 'DONE': break
        print(f'item: {item}')
    send('OTHER')

Вывод сервера:

connect: ('127.0.0.1', 13338)
cmd: TEST
cmd: LIST
cmd: OTHER
disconnect: ('127.0.0.1', 13338)

Клиентский вывод:

TEST
LIST
item: C1
item: C2
item: C3
OTHER
...