博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
原创博客>>>解决粘包问题的方法
阅读量:5291 次
发布时间:2019-06-14

本文共 3110 字,大约阅读时间需要 10 分钟。

目录

原创博客>>>解决粘包问题的方法

  • 服务端:

    import socketimport structservice=socket.socket()service.bind(('127.0.0.1',8081))while True:    service.listen(5)    conn,address=service.accept()    print('有客户端连接进来了,地址如下',address)    data_len_byte=conn.recv(4)    # print(data_len_byte)    data_len=struct.unpack('i',data_len_byte)[0]#把数据长度的字节码再转int    data=conn.recv(data_len)    print('我收到了客户端的数据',data)    conn.send(b'ok')
  • 客户端

    import socketimport structclient=socket.socket()client.connect(('127.0.0.1', 8081))msg=input('helloword,input>>>>')# print(msg.encode('utf8'))#把数据字节码的长度转为字节码  这个字节码固定是四位的msg_len_byte=struct.pack('i',len(msg.encode('utf8')))client.send(msg_len_byte)msg_byte=msg.encode('utf8')client.send(msg_byte)data=client.recv(4)print('来自服务端的信息',data)

    1740897-20190907173048350-1904890650.png

    以上的解决思路:客户端第一个send()往服务端发送固定长度为4 的字节码(客户端接下来要发送的真正内容的长度的字节码) ,然后服务端这边,第一个的recv(4)接收到这个数据的时候,就等于获取到了客户端接下来要发送的数据的字节码长度len,这个len作为接下来服务端接收的recv(len)的长度参数,客户端发送真正的数据的字节码后,服务端的recv(len)就完完整整的收到了真正的数据,一字不少不多。

    以上思路是针对于一种是粘在一起的包都是完整的数据包的粘包问题

    以下思路是针对于粘在一起的包有不完整的包。

    于是对以上的问题再次升级,代码放出

    • 服务端
    import socketimport subprocessimport structsoc=socket.socket(socket.AF_INET,socket.SOCK_STREAM)soc.bind(('127.0.0.1',8001))soc.listen(3)while True:    print('等待客户端连接')    conn,addr=soc.accept()    print('有个客户端连接上了',addr)    while True:        try:            data=conn.recv(1024)            if len(data)==0:                break            print(data)            obj = subprocess.Popen(str(data,encoding='utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)            #执行正确的结果 b 格式,gbk编码(windows平台)            msg=obj.stdout.read()            #发送的时候需要先把长度计算出来            #头必须是固定长度            #先发4位,头的长度            import json            dic={'size':len(msg)}            dic_bytes=(json.dumps(dic)).encode('utf-8')            #head_count是4个字节的长度            head_count=struct.pack('i',len(dic_bytes))            print(dic)            conn.send(head_count)            #发送头部内容            conn.send(dic_bytes)            #发了内容            conn.send(msg)        except Exception:            break    # 关闭通道    conn.close()# 关闭套接字soc.close()
    • 客户端
    import socketimport structimport jsonsoc=socket.socket()soc.connect(('127.0.0.1',8001))while True:    in_s=input('请输入要执行的命令:')    soc.send(in_s.encode('utf-8'))    #头部字典的长度    head_dic_len=soc.recv(4)    #解出真正的长度    head_l=struct.unpack('i',head_dic_len)[0]    #byte 字典的长度    #收真正的头部字典    dic_byte=soc.recv(head_l)    head=json.loads(dic_byte)    print(head)    l=head['size']    count=0    data_total=b''    print(l)  #核心代码    while count
    =1024: #总数据长度-count(目前收到多少,count就是多少) 如果还大于1024 ,在收1024 data=soc.recv(1024) else: #总数据长度-count(目前收到多少,count就是多少) 如果小于1024,只收剩下的部分就可 data=soc.recv(l-count) data_total+=data count+=len(data) print(str(data_total,encoding='gbk'))

    思路:为了把粘在一起的包有不完整的包问题更加明显,特意找了subprocess模块,这个模块可以模拟cmd,输入tasklist命令的结果是很长的字节码,一般情况下recv(n)第一次只能打印前n个字节码,总之一次只能打印不完整的数据,必须多次打印接下来剩下的数据,于是就套用了while true,通过while true循环 拼接字节码 拼接整个数据的字节码,if判断读到的剩下数据是否到尾巴,到了尾巴将while 终止break,最后 将完整的数据的字节码打印出来。

转载于:https://www.cnblogs.com/demiao/p/11481992.html

你可能感兴趣的文章
Could not load driverClass com.mysql.jdbc.Driver错误
查看>>
路飞学城-爬虫集训营-第一章
查看>>
技术人员应真正学会的第二课程
查看>>
[洛谷P3628] [APIO2010]特别行动队
查看>>
《集体智慧编程》第12章:算法总结
查看>>
Hbase配置运行
查看>>
【转载】"30年---我与赛灵思FPGA的故事”:ZYNQ-7000使用总结(6)——AXI接口简述...
查看>>
Jenkins系列-Jenkins通过Publish over SSH插件实现远程部署
查看>>
ERR: Failed to complete setup of assembly (hr = 0x8007000b). Probing terminated.
查看>>
Java 中int、String的类型转换
查看>>
Oracle 查看正在执行的SQL语句
查看>>
HDU 1069 Monkey and Banana
查看>>
一个类有两个方法,其中一个是同步的,另一个是非同步的; 现在又两个线程A和B,请问:当线程A访问此类的同步方法时,线程B是否能访问此类的非同步方法?...
查看>>
consonant combination
查看>>
堆排序
查看>>
elk报错解决
查看>>
centos6更改时区
查看>>
struts中请求数据自动封装
查看>>
C# 高斯消元项目运用
查看>>
WUST 设计模式 实验一 单例模式的应用
查看>>