Python案例-网络编程-socket-解决ssh消息粘包问题
废话不多说,上代码,具体逻辑分析详见注释,本次目的是解决上一个案例中出现的,超出recv(num)设置的值时,信息包会不完整,并与下一个client请求的信息包粘在一块,也就是俗称的粘包问题。 Server端代码:#!/usr/bin/env python#--coding = utf-8#Author Allen Leeimport socket,subprocess,socke
·
废话不多说,上代码,具体逻辑分析详见注释,本次目的是解决上一个案例中出现的,超出recv(num)设置的值时,信息包会不完整,并与下一个client请求的信息包粘在一块,也就是俗称的粘包问题。
Server端代码:
#!/usr/bin/env python
# --coding = utf-8
# Author Allen Lee
import socket,subprocess,socketserver
ip_port = ('10.12.4.82',8088,)
server = socket.socket()
server.bind(ip_port)
server.listen(0)
while True:
conn,addr = server.accept()
print(addr)
while True:
try:
res_data = conn.recv(1024)
if len(res_data) == 0 :break
ret = subprocess.Popen(str(res_data,encoding='utf-8'),shell=True,stdout=subprocess.PIPE)
res_msg = ret.stdout.read()
if len(res_msg) == 0:
send_data = 'cmd_err'
else:
send_data = str(res_msg,encoding='gbk')
print(send_data, type(send_data))
#通知客户端,本次包的总大小,并打上‘ready’的signal,让client来抓取,注意这里用“|”为分隔符
send_tag = 'ready|%d' %(len(res_msg))
conn.send(bytes(send_tag,encoding='utf-8'))
#为了调试代码进度所添加的输出
print(send_tag)
#cilent在收到‘ready’的标签后,给服务端回一个‘start’,通知服务端可以发包
recv_data = conn.recv(1024)
recv_tag = str(recv_data,encoding='utf-8')
#在服务端接收到来时client的确认信息之后,则开始发送client请求的信息;
if recv_tag == 'start':
conn.send(bytes(send_data,encoding='utf-8'))
else:
conn.send(bytes('do not receive the start signal',encoding='utf-8'))
except Exception:
break
conn.close()
client端代码:
#!/usr/bin/env python
# --coding = utf-8
# Author Allen Lee
import socket
server_port = ('10.12.4.82',8088,)
client = socket.socket()
client.connect(server_port)
while True:
send_data = input('>>: ').strip()
if len(send_data) == 0:continue
if send_data == 'exit':break
send_msg = bytes(send_data,encoding='utf-8')
client.send(send_msg)
res_data = client.recv(1024)
res_tag = str(res_data,encoding='utf-8')
#client接收并解析服务端发回的信息是否是ready开头的,以此判断是否要开始发包了
if res_tag.startswith('ready'):
#将ready后的数字传给res_total,用于之后的信息回显,同理也可以来做一个进度条的显示功能
res_total = int(res_tag.split('|')[1])
#初始化当前接收的信息节点数值
res_now = 0
# cilent在收到‘ready’的标签后,给服务端回一个‘start’,通知服务端可以发包
client.send(bytes('start',encoding='utf-8'))
#在当前信息值不大于总值的情况下,循环获取并打印服务端发过来的信息
while res_now <= res_total:
#设置recv最小接收信息单元 的字节数
res_data = client.recv(1024)
res_now += len(res_data)
print('total:%s----now:%s'%(res_total,res_now))
print(str(res_data,encoding='utf-8'))
client.close()
解决了粘包的问题,就可以进一步实现scp的功能了,这里需要大家理解一个情况:
所有的图片、文件、视频、音频 等,其实底层传输都是通过二进制(0101)的编码,因此我们完全可以将 全文件类型 解码为bytes类型,然后逐行以读取file的形式将信息发去client端,client端再进行拼接,最后以原有的‘文件名+后缀名’命名。
详细实现情况请见本系列下一篇,关于scp的实现代码
更多推荐
已为社区贡献10条内容
所有评论(0)