码迷,mamicode.com
首页 > 编程语言 > 详细

python——黏包

时间:2018-01-26 17:08:57      阅读:210      评论:0      收藏:0      [点我收藏+]

标签:png   pwd   struct   blank   res   防止   lis   ndt   recv   

 黏包现象

基于tcp先制作一个远程执行命令的程序(命令ls -l ; lllllll ; pwd)

res=subprocess.Popen(cmd.decode(utf-8),
shell=True,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE)

的结果的编码是以当前所在的系统为准的,如果是windows,那么res.stdout.read()读出的就是GBK编码的,在接收端需要用GBK解码

且只能从管道里读一次结果

同时执行多条命令之后,得到的结果很可能只有一部分,在执行其他命令的时候又接收到之前执行的另外一部分结果,这种显现就是黏包。

基于tcp协议实现的黏包

import socket
import subprocess
sk = socket.socket()
sk.connect((127.0.0.1,8090))
while True:
    cmd = sk.recv(1024).decode(gbk)
    ret = subprocess.Popen(cmd,shell=True,
                           stdout=subprocess.PIPE,
                           stderr=subprocess.PIPE)
    std_out = stdout :+(ret.stdout.read()).decode(gbk)
    std_err = stderr :+(ret.stderr.read()).decode(gbk)
    print(std_out)
    print(std_err)
    sk.send(std_out.encode(utf-8))
    sk.send(std_err.encode(utf-8))
sk.close()
import socket
sk = socket.socket()
sk.bind((127.0.0.1,8090))
sk.listen()

conn,addr = sk.accept()
while True:
    cmd = input(>>>)
    conn.send(cmd.encode(utf-8))
    ret = conn.recv(1024).decode(utf-8)
    print(ret)

conn.close()
sk.close()

基于udp协议实现的黏包

import socket
import subprocess
sk = socket.socket(type=socket.SOCK_DGRAM)
addr = (127.0.0.1,8090)
sk.sendto(吃了么.encode(utf-8),addr)
while True:
    cmd,addr = sk.recvfrom(10000)
    ret = subprocess.Popen(cmd.decode(gbk),shell=True,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE)
    std_out = stdout :+(ret.stdout.read()).decode(gbk)
    std_err = stderr :+(ret.stderr.read()).decode(gbk)
    print(std_out)
    print(std_err)
    sk.sendto(std_out.encode(utf-8),addr)
    sk.sendto(std_err.encode(utf-8),addr)
sk.close()
import socket
sk = socket.socket(type=socket.SOCK_DGRAM)
sk.bind((127.0.0.1,8090))
msg,addr = sk.recvfrom(10240)
while True:
    cmd = input(>>>)
    if cmd == q:
        break
    sk.sendto(cmd.encode(utf-8),addr)
    msg,addr = sk.recvfrom(10240)
    print(msg.decode(utf-8))

sk.close()


# udp
# udp 不会黏包
# udp 会丢包

注意:只有TCP有粘包现象,UDP永远不会粘包

基于tcp协议特点的黏包现象成因 

技术分享图片

例如基于tcp的套接字客户端往服务端上传文件,发送时文件内容是按照一段一段的字节流发送的,在接收方看了,根本不知道该文件的字节流从何处开始,在何处结束

此外,发送方引起的粘包是由TCP协议本身造成的,TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一个TCP段。若连续几次需要send的数据都很少,通常TCP会根据优化算法把这些数据合成一个TCP段后一次发送出去,这样接收方就收到了粘包数据。

UDP不会发生黏包

 

UDP(user datagram protocol,用户数据报协议)是无连接的,面向消息的,提供高效率服务。 
不会使用块的合并优化算法,, 由于UDP支持的是一对多的模式,所以接收端的skbuff(套接字缓冲区)采用了链式结构来记录每一个到达的UDP包,在每个UDP包中就有了消息头(消息来源地址,端口等信息),这样,对于接收端来说,就容易进行区分处理了。 即面向消息的通信是有消息保护边界的。 
对于空消息:tcp是基于数据流的,于是收发的消息不能为空,这就需要在客户端和服务端都添加空消息的处理机制,防止程序卡住,而udp是基于数据报的,即便是你输入的是空内容(直接回车),也可以被发送,udp协议会帮你封装上消息头发送过去。 
不可靠不黏包的udp协议:udp的recvfrom是阻塞的,一个recvfrom(x)必须对唯一一个sendinto(y),收完了x个字节的数据就算完成,若是y;x数据就丢失,这意味着udp根本不会粘包,但是会丢数据,不可靠。

 

python——黏包

标签:png   pwd   struct   blank   res   防止   lis   ndt   recv   

原文地址:https://www.cnblogs.com/chenshuaiv587/p/8360055.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!