Socket 强制不同的 TCP 包

问题描述 投票:0回答:1

我目前正在用 Python 编写一些关于我的 TCP 服务器的测试。我想测试当一条消息被分成多个不同的包时的行为。如何强制操作系统实际发送消息而不是等待更多数据以避免发送小包?只是等待

time.sleep
不是一个选择。

    def send(self, msg: Union[str,List[str]]):
        if isinstance(msg, list):
            for m in msg:
                self.s.sendall(m.encode())
        else:                
            self.s.sendall(msg.encode())
python sockets
1个回答
0
投票

您的服务器需要知道什么构成“消息”。常见的策略是以客户端和服务器都能理解的格式发送重要消息的长度。

您可以使用 struct 模块来打包和解包数字数据来管理它。

这是一个完整的工作示例,您可以改编:

from socket import socket, AF_INET, SOCK_STREAM
from threading import Thread
from struct import pack, unpack, calcsize
from select import select

ADDRESS = ("localhost", 1234)
FORMAT = "!L"
FMTLEN = calcsize(FORMAT)

def read(conn, nbytes):
    buffer = bytes()
    while len(buffer) < nbytes:
        select([conn], [], [])
        buffer += conn.recv(nbytes - len(buffer))
    return buffer

def getmessage(conn):
    b = read(conn, FMTLEN)
    mlen, *_ = unpack(FORMAT, b)
    return None if mlen == 0 else read(conn, mlen)

def server():
    with socket(AF_INET, SOCK_STREAM) as s:
        s.bind(ADDRESS)
        s.listen()
        try:
            conn, _ = s.accept()
            while msg := getmessage(conn):
                print(msg.decode())
        finally:
            conn.close()

if __name__ == "__main__":
    thread = Thread(target=server)
    thread.start()
    s = socket(AF_INET, SOCK_STREAM)
    try:
        s.connect(ADDRESS)
        messages = ["a", "b", "Hello world!"]
        for message in messages:
            mlen = pack(FORMAT, len(message))
            packet = mlen + message.encode()
            s.sendall(packet)
        s.sendall(pack(FORMAT, 0))
    finally:
        s.close()
    thread.join()
© www.soinside.com 2019 - 2024. All rights reserved.