Есть ли способ избежать пропущенных байтов при передаче данных через сокет Python? - PullRequest
0 голосов
/ 27 мая 2019

У меня есть два разных клиента Python, взаимодействующих друг с другом (Клиент A и Клиент B) через сервер внешнего узла в Интернете.Клиент A должен отправить много идентифицированных сообщений за короткий период времени клиенту B, где сервер узла отвечает за пересылку всех полученных сообщений от A к B.

Что происходит, так это то, что клиент A перезаписывает некоторое сообщение,

Я обнаружил проблему на клиенте B, где я анализирую сообщения.Однако проблема возникает при передаче сообщений между клиентом A и сервером Node, потому что я уже могу видеть испорченное сообщение в журналах сервера узлов.

Я покажу некоторый псевдокод вместе с некоторыми журналами, касающимисяошибка (только для клиента A и сервера):

клиент A

код ... сокет импорта

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.connect((HOST, PORT))

...

while not END:
    #Prepare message_to_clinet

    #If I uncomment this timer, the error will not appear (or appear later)
    #time.sleep(0.2)

    # I have tried either sendall and send. But it seems that is not effective
    server_socket.sendall(message_to_client)
    print '(Sent):' + message_to_client

Регистрируется при возникновении ошибкиПредставьте, что я хочу 100 раз отправить сообщение: «Где ошибка?»

...
(Sent): Where is the bug?
(Sent): Where is the bug?
(Sent): Where is the bug?
(Sent): Where is the bug?
(Sent): Where is the bug?
...

Узел

Код

const net = require('net');
const tcpServer = net.createServer(connection.requestHandler);
tcpServer.listen(connection.port, (err) => {
    if (err) {
        return console.log('tcp socket error', err);
    }

    console.log(`tcp socket listening on ${connection.port}`);
});

...

const requestHandler = (sock) => {   
    sock.on('data', (data) => {
        const protocol_message = new Buffer(data).toString('ascii');

        //Send this message to remote client
        currentConnection.sendMessagesToClient(protocol_message)
        console.log('Received: ' + protocol_message)
    }
}

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

...
Received: Where is the bug? Where is the bug? Where is the bug?  Where is the bug?Where is the bug?
Received: Where is the bug? Where is the bug? Where is the bug?  Where is the bug?Where is the bug?
Received: Where is thWhere is the bug? Where is the bug?Where is the bug?
...

Здесь я вижу, что одно из 100 сообщений, которые я неоднократно отправлял, не работает.Однако на клиенте А все, видимо, хорошо.

Кто-нибудь знает, какова возможная причина этой ошибки?

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

РЕДАКТИРОВАТЬ: я использую Python 2.7

Ответы [ 2 ]

1 голос
/ 27 мая 2019

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

Хотя это была ошибка на стороне сервера, я нашел ее только потому, что провел некоторое исследование и пришел к выводу, что TCP гарантирует тот же порядок, но он может разбить данные на куски.

В любом случае, спасибо!

0 голосов
/ 27 мая 2019

Вы всегда можете попробовать:

s.recv #insert increased buffer size here#

Может работать.

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