Skip to main content
 首页 » 编程设计

Python 套接字之以 10 字节为单位发送字符串

2025年05月04日22me-sa

我有一个简单的 tcp 套接字程序,我想以 10 个字节的 block 的形式发送字符串。服务器将加入 block 。 但是我不确定如何将字符串拆分为二进制文件以及如何发送二进制文件 block 。我不想一次发送 512 个字节,而是想多次发送 10 个字节。

我找到了一个模块 Pickle,它可以将数据序列化为字节串(?),但是我该如何应用 socket.send() 呢?

服务器:

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
server_socket.bind(("", my_port)) 
server_socket.listen(5) 
client_socket, address = server_socket.accept() 
data = client_socket.recv(512) 

客户:

message = "some string I want to send in chunks" 
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
client_socket.connect((host, my_port)) 
client_socket.send(message) 
client_socket.close() 

请您参考如下方法:

首先,您的代码实际上并不是一次发送 512 个字节,而是一次接收 512 个字节。

现在,我认为您实际上是在问两个问题。

  1. 如何通过 TCP 连接一次发送 10 个字节(您正在使用 socket.SOCK_STREAM)
  2. 如何使用 Python 套接字发送原始字节。

让我们首先回答 2:如果您调用 socket.send在字节串上,它应该以二进制形式作为 TCP 有效载荷发送出去。

对于 1.,最简单的方法是将数据分成 block (现在您知道您正在对字符串进行操作,您可以简单地使用切片操作来做到这一点(参见 Python tutorial on strings - 例如 s[0:10], s[10:20] 等)。接下来,您需要确保这些切片是单独发送的。这可以通过调用 socket 来完成。发送,但问题是,您的 TCP/IP 堆栈可能会将这些分组到数据包中,即使您不希望这样做 - 毕竟您已经要求它为您提供一个流 套接字,socket.SOCK_STREAM。如果您正在写入文件,在这种情况下您要做的是刷新文件,但这对于 Python 套接字来说似乎并不容易(参见 this question )。

现在,我认为这个问题的答案,说这是不可能的,是不太正确的。看来 Scapy会让你发送 10 字节的 TCP block (我从 here 得到了 chunks() 函数)。我在 wireshark 中检查了它并多次尝试并获得了一致的结果,但我没有检查实现以确保这一定会发生。

您可能应该问自己为什么要以 10 字节为单位发送数据,而不是让 TCP 处理它的设计目的,并考虑使用分隔符。

无论如何,这是使用 Scapy 的代码(有趣的事实:看起来运行它不需要 root 权限):

客户:

from scapy.all import * 
 
import socket 
host = '192.168.0.x' #replace with your IP 
my_port = 3002 
message = "some string I want to send in chunks" 
 
def chunks(lst, n): 
    "Yield successive n-sized chunks from lst" 
    for i in xrange(0, len(lst), n): 
        yield lst[i:i+n] 
 
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
client_socket.connect((host, my_port)) 
ss=StreamSocket(client_socket,Raw) 
for chunk in chunks(message, 10): 
    print "sending: " + chunk 
    ss.send(Raw(chunk) ) 
 
client_socket.close() 

服务器:

import socket 
my_port=3002 
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
server_socket.bind(("", my_port)) 
server_socket.listen(5) 
client_socket, address = server_socket.accept() 
while (True): 
    data = client_socket.recv(512) 
    if (data): 
        print data 
    else: 
        break