我又来了, 又是关于 socket 的

2020-06-16 22:53:49 +08:00
 18870715400

附上代码:

server 端

from socketserver import BaseRequestHandler, ThreadingTCPServer


class Handler(BaseRequestHandler):

    def setup(self) -> None:
        self.request.settimeout(1)

    def handle(self):
        while 1:
            try:
                data = "这是主机端的信息"
                self.request.sendall(data.encode("utf-8"))
            except BaseException as e:
                print(e)
                print("关闭连接:{}".format(self.client_address[0]))
                break


if __name__ == '__main__':
    host = ("localhost", 8000)
    server = ThreadingTCPServer(host, Handler)
    server.serve_forever()

client 端

import socket
import time


client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

host = ("localhost", 8000)

client.connect(host)


while 1:
    data = client.recv(2000)
    if len(data) <= 0:
        break

    print("从主机端接受信息:{}".format(data.decode()))
    # time.sleep(1)

运行 client 的时候有的时候会报错,'utf-8' codec can't decode bytes in position

但是如果在 server 端 self.request.sendall 发送英文的时候就不会报错, 个人估计是因为编码后的中文传输的时候 client 端接收的数据不够完整, 比如一个 编译后的 字节数据是 \xe5\x93\x88 但是接收的时候只有接收到 xe5\x9 导致 client 端解析的时候出错了, 大家有什么方法保证数据的完整性么

2898 次点击
所在节点    Python
15 条回复
18870715400
2020-06-16 22:58:49 +08:00
还有, 关于 self.request.recv()的 函数怎么不阻塞,

我在 Handler 中的 setup 函数中设置 self.request.settimeout(0) 之后会报一个 参考的对象类型不支持尝试的操作错误, 应该怎么解决呢
est
2020-06-16 23:47:00 +08:00
还是去学一下 python 基础吧。
CEBBCAT
2020-06-17 00:04:50 +08:00
你还需要学习 TCP 基础,再出错也不至于传半个字节给 Python 呐……

另外你这是面向论坛工作吗?
Caratpine
2020-06-17 00:07:27 +08:00
学习 TCP +1,TCP 是流传输。
一种办法是在传送消息的时候把消息长度作为头信息也传给客户端。
wy
2020-06-17 00:59:00 +08:00
可以参考一下 HTTP 中的 chunk 编码方式。简单来说就是先发送一个长度,然后再发对应长度的数据。这样客户端就去可以判断数据是否完整了。
wangyzj
2020-06-17 01:38:04 +08:00
data = client.recv(24)
这样就不会报错了
哈哈哈
yeept
2020-06-17 08:32:03 +08:00
Socket 一定要注意处理数据边界,可参考 #5 方式
18870715400
2020-06-17 09:05:07 +08:00
好的,
mingl0280
2020-06-17 10:11:00 +08:00
TCP 基础常识:TCP 是一个字节流协议,客户端或服务器收到的字节流有多长没人知道.TCP 只保证字节流的顺序是正确的.这也是为什么 TCP 需要一个上层的协议来保证消息完整性的原因.
cweijan
2020-06-17 11:18:25 +08:00
楼上正解
hankai17
2020-06-17 13:53:43 +08:00
实现一套 http 用来收发
Chenamy2017
2020-06-17 14:13:14 +08:00
1. 学习下 TCP 数据流处理吧
2. 调试时你可以将收到的数据打印出来(用十六进制)看看你都收到了些什么数据,看到数据你就明明白白的了
gesse
2020-06-17 15:57:14 +08:00
client.recv(2000)

你这个把 utf-8 编码截断了。

>>> len('这是主机端的信息'.encode('utf-8'))
24

你把 2000 改成 24 的倍数就可以了。
18870715400
2020-06-17 16:16:34 +08:00
@gesse 你的这个方法的确有用, 但是如果服务端发送的数据是不定长的呢?不是整倍数
18870715400
2020-06-17 16:24:55 +08:00
我明白了各位所说的, 我的原意是 比如说 哈 的编码是 b'\xe5\x93\x88' 但是由于 recv 中 buff_size 限制原因导致只取到了前两个字节 b'\xe5\x93' 所以 decode 的时候会报错, 我现在知道 \xe5 是一个完整的字节, 所以问的时候才会犯上面的错误, 现在是需要如何将完整的数据拼接起来

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/682191

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX