Как получать и обрабатывать несколько сокетов TCP-потока? - PullRequest
0 голосов
/ 25 мая 2020

Я хотел бы отправить местоположение движущейся точки на сервер через TCP с модулем сокета. Расположение этой точки обновляется на каждой итерации for l oop и отправляется в виде кортежа (x, y), сериализованного с помощью методов pickle dumps.

Проблема:

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

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

Код :

- на стороне клиента -

#Python3.7
import socket
import pickle
import math

HOST = "127.0.0.1" 
PORT = 12000

den = 20
rad = 100
theta = math.tau / den

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
    sock.connect((HOST, PORT)) #connect to server

    for step in range(1000):
        i = step%den
        x = math.cos(i*theta) * rad
        y = math.sin(i*theta) * rad
        data = pickle.dumps((x, y), protocol=0) 
        sock.sendall(data) 

- на стороне сервера -

#Jython2.7
import pickle
import socket

HOST = "127.0.0.1"   
PORT = 12000

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)

while True:
    connection, address = s.accept()

    if connection:
        data = connection.recv(4096)
        print(pickle.loads(data)) # <-- only print once (first location)

1 Ответ

2 голосов
/ 25 мая 2020

Вам необходимо установить соединение, address = s.accept () за пределами while l oop, иначе ваш сервер будет каждый раз ждать нового соединения.

У вас также есть проблема с тем, как ваш получают данные. connection.recv(4096) будет возвращать любое количество байтов от 0 до 4096 не каждый раз, когда принимается полное сообщение с «данными». Чтобы справиться с этим, вы можете отправить заголовок перед отправкой вам json, указывающий, сколько данных должно быть получено. Добавив заголовок, вы убедитесь, что отправляемые вами сообщения с данными будут получены правильно.

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

import pickle
import socket
import struct

HEADER_SIZE = 4
HOST = "127.0.0.1"
PORT = 12000


def receive(nb_bytes, conn):
    # Ensure that exactly the desired amount of bytes is received
    received = bytearray()
    while len(received) < nb_bytes:
        received += conn.recv(nb_bytes - len(received))

    return received

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
connection, address = s.accept()

while True:
    # receive header
    header = receive(HEADER_SIZE, connection)
    data_size = struct.unpack(">i", header)[0]
    # receive data
    data = receive(data_size, connection)
    print(pickle.loads(data))

Клиент

import socket
import pickle
import math

HEADER_SIZE = 4
HOST = "127.0.0.1"
PORT = 12000

den = 20
rad = 100
theta = math.tau / den

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
    sock.connect((HOST, PORT)) #connect to server

    for step in range(1000):
        i = step%den
        x = math.cos(i*theta) * rad
        y = math.sin(i*theta) * rad
        data = pickle.dumps((x, y), protocol=0)
        # compute header by taking the byte representation of the int
        header = len(data).to_bytes(HEADER_SIZE, byteorder ='big')
        sock.sendall(header + data)

Надеюсь, это поможет

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