【问题标题】:Python sockets - sending string in chunks of 10 bytesPython 套接字 - 以 10 个字节的块发送字符串
【发布时间】:2012-11-23 07:48:23
【问题描述】:

我有一个简单的 tcp 套接字程序,我想以 10 个字节的块发送字符串。服务器将加入块。 但是我不确定如何将字符串拆分为二进制文件以及如何发送二进制文件块。而不是一次发送 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()

【问题讨论】:

标签: python sockets


【解决方案1】:

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

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

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

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

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

现在,我认为这个问题的答案,说这是不可能的,并不完全正确。看来Scapy 会让你发送 10 字节的 TCP 块(我从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

【讨论】:

  • 为什么不每十个字节打开和关闭客户端套接字?
  • 一般情况下不太一样。根据在套接字上运行的协议,您可能需要再次交换标头、登录等。在某些情况下,您提出的建议甚至可能无法实现,例如,如果您想模拟在 X 字节中上传更大的文件通过 HTTP 分块,因为文件传输将被中止(至少在幼稚的实现中)
猜你喜欢
  • 2015-01-22
  • 1970-01-01
  • 2014-02-09
  • 1970-01-01
  • 2018-06-13
  • 2020-08-29
  • 1970-01-01
  • 2013-06-30
  • 1970-01-01
相关资源
最近更新 更多