先声明,我知道没有粘包这种东西,关键是自己应用层处理好 socket 流的边界就行。
那么最常见的就是就是[header][body]这种,header 固定 4 字节大端 int32 代表 body 长度,那么我的写法如下
# server.py
body_length = sock.recv(4) # 这里就不写 struct.unpack 了,意思意思
data = []
while body_length:
bytes = sock.recv(body_length)
body_length -= len(bytes)
if not bytes:
# 不写这个,如果客户端故意 header 传入的长度 > body,会无限循环?
break
data.append(bytes)
疑问 1:网上看到的 recv(4)好像都是直接写的,请问这个 recv(4)有必要向下面一样 while 吗? ps.我觉得可能还是要 socket.recv
为了看看 python 自己怎么写的,以 3.7.9 python 为例,我看了 wsgiref.WSGIRequestHandler, 简单逻辑如下
# 在 accept 拿到 client_socket 之后
self.connection = client_socket
self.rbufsize = -1
self.rfile = self.connection.makefile('rb', self.rbufsize)
self.raw_requestline = self.rfile.readline(65537)
发现 http header 的处理好像都是直接用的 readline,然后我看 readline 的解释是会保证正确的按行读取.
疑问 2:如果我也用 makefile('rb', -1)的方式,那么 self.rfile.read(n) 是不是可信的 n 字节数据呢?
是否要像 sock.recv 一样自己多次调用?还是说不用[header][body]这种固定字节处理 header, 转而使用 header\nbody 这种,也像 http 处理一样直接 readline
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.