如何接收和处理多个 TCP 流套接字?

How to receive and handle multiple TCP stream sockets?

我想使用套接字模块通过 TCP 将移动点的位置发送到服务器。该点位置在 for 循环的每次迭代中更新,并以已使用 pickle dumps 方法序列化的元组 (x, y) 的形式发送。

问题:

在服务器端,我似乎只能从该循环的第一次迭代中接收到位置信息。就好像后面所有的更新位置都在这个过程中被跳过或丢失了。

我不能确定这种行为背后的原因是什么,但我敢打赌我在服务器端的设置不正确。我怀疑数据已完全发送,但由于我可能在使用套接字模块时犯了一些错误而在接收时没有得到充分处理(我对网络接口的世界是全新的)。

代码:

--客户端--

#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)

您需要将 connection, address = s.accept() 放在 while 循环之外,否则您的服务器每次都会等待新的连接。

您接收数据的方式也有问题。 connection.recv(4096) 将 return 0 到 4096 之间的任意数量的字节,而不是每次收到完整的 "data" 消息时。要处理此问题,您可以在向您发送 json 之前发送一个 header,指示应接收多少数据 通过添加 header,您将确保正确接收您发送的数据消息。

本例中的header是一个四字节的整数,表示数据的大小。
服务器

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)

希望对您有所帮助