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()
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)
#! /usr/bin/env python
# coding=utf-8
from socketserver import BaseRequestHandler, ThreadingTCPServer
class Handler(BaseRequestHandler):
def setup(self) -> None:
self.request.settimeout(1)
def handle(self):
while 1:
try:
data = "这是主机端的信息"
length = len(data.encode())
length_string = "0" * (8 - len(str(length))) + str(length)
print(length_string)
self.request.sendall(length_string.encode() + data.encode())
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()
#! /usr/bin/env python
# coding=utf-8
import socket
import time
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = ("localhost", 8000)
client.connect(host)
remainging = b""
while 1:
data = client.recv(2001)
if len(data) <= 0:
break
data = remainging + data
coursor = 0
while coursor < len(data):
size = int(data[coursor:8+coursor].decode())
infos = data[8+coursor:8+coursor+size].decode()
coursor = 8 + coursor + size
print(infos)
print(coursor, 111)
if len(data) - coursor <= 8:
break
else:
if coursor + int(data[coursor:coursor+8].decode()) + 8 > len(data):
break
remainging = data[coursor:]
time.sleep(1)
1
18870715400 OP 还有, 关于 self.request.recv()的 函数怎么不阻塞,
我在 Handler 中的 setup 函数中设置 self.request.settimeout(0) 之后会报一个 参考的对象类型不支持尝试的操作错误, 应该怎么解决呢 |
2
est 2020-06-16 23:47:00 +08:00
还是去学一下 python 基础吧。
|
3
CEBBCAT 2020-06-17 00:04:50 +08:00 via Android
你还需要学习 TCP 基础,再出错也不至于传半个字节给 Python 呐……
另外你这是面向论坛工作吗? |
4
Caratpine 2020-06-17 00:07:27 +08:00
学习 TCP +1,TCP 是流传输。
一种办法是在传送消息的时候把消息长度作为头信息也传给客户端。 |
5
wy 2020-06-17 00:59:00 +08:00 via Android
可以参考一下 HTTP 中的 chunk 编码方式。简单来说就是先发送一个长度,然后再发对应长度的数据。这样客户端就去可以判断数据是否完整了。
|
6
wangyzj 2020-06-17 01:38:04 +08:00
data = client.recv(24)
这样就不会报错了 哈哈哈 |
7
yeept 2020-06-17 08:32:03 +08:00
Socket 一定要注意处理数据边界,可参考 #5 方式
|
8
18870715400 OP 好的,
|
9
mingl0280 2020-06-17 10:11:00 +08:00
TCP 基础常识:TCP 是一个字节流协议,客户端或服务器收到的字节流有多长没人知道.TCP 只保证字节流的顺序是正确的.这也是为什么 TCP 需要一个上层的协议来保证消息完整性的原因.
|
10
cweijan 2020-06-17 11:18:25 +08:00
楼上正解
|
11
hankai17 2020-06-17 13:53:43 +08:00
实现一套 http 用来收发
|
12
Chenamy2017 2020-06-17 14:13:14 +08:00
1. 学习下 TCP 数据流处理吧
2. 调试时你可以将收到的数据打印出来(用十六进制)看看你都收到了些什么数据,看到数据你就明明白白的了 |
13
gesse 2020-06-17 15:57:14 +08:00
client.recv(2000)
你这个把 utf-8 编码截断了。 >>> len('这是主机端的信息'.encode('utf-8')) 24 你把 2000 改成 24 的倍数就可以了。 |
14
18870715400 OP @gesse 你的这个方法的确有用, 但是如果服务端发送的数据是不定长的呢?不是整倍数
|
15
18870715400 OP 我明白了各位所说的, 我的原意是 比如说 哈 的编码是 b'\xe5\x93\x88' 但是由于 recv 中 buff_size 限制原因导致只取到了前两个字节 b'\xe5\x93' 所以 decode 的时候会报错, 我现在知道 \xe5 是一个完整的字节, 所以问的时候才会犯上面的错误, 现在是需要如何将完整的数据拼接起来
|