码迷,mamicode.com
首页 > 其他好文 > 详细

subprocess、struct

时间:2017-11-28 16:47:35      阅读:135      评论:0      收藏:0      [点我收藏+]

标签:文件   class   函数返回   pop   str   hash   utf-8   提取   .so   

要点:

  1. 报头  固定长度bytes类型(18)

1、粘包现象

  粘包就是在获取数据时,出现数据的内容不是本应该接收的数据,如:对方第一次发送hello,第二次发送world,
我放接收时,应该收两次,一次是hello,一次是world,但事实上是一次收到helloworld,一次收到空,这种现象
叫粘包

  只有TCP有粘包现象,TCP协议是面向流的协议,这也是容易出现粘包问题的原因。例如基于tcp的套接字客户端往服务端上传文件,发送时文件内容是按照一段一段的字节流发送的,在接收方看了,根本不知道该文件的字节流从何处开始,在何处结束。所谓粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。

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

2、两种情况下会发生粘包。

  发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据了很小,会合到一起,产生粘包)

  接收方不及时接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端只收了一小部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包) 

3.粘包的解决

  是通过设置报头,在传信息之前,先把该信息的报头传给对方,在传该信息,就不会出现粘包
  报头是一个字典,它含有信息的大小,还有可以有文件的名称,文件的hash值,如下
  head_dic={‘size‘:len(data),‘filename‘:filenaem,‘hash‘:hash值},如果还有,可以继续在字典中加

服务端

#1、执行客户端发送的指令
import socket
import subprocess
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.bind((127.0.0.1,8090))
phone.listen(5)
while True:
    conn,addr=phone.accept()
    print(IP:%s PORT:%s %(addr[0],addr[1]))
    while True:
        try:
            cmd=conn.recv(1024)
            if not cmd:break
            #执行命令
            obj=subprocess.Popen(cmd.decode(utf-8),shell=True,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE
                                 )
            stdout=obj.stdout.read()
            stderr=obj.stderr.read()
            conn.send(stdout+stderr)
        except Exception:
            break
    conn.close()
phone.close()

 

客户端:

import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect((127.0.0.1,8090))
while True:
    cmd=input(>>:).strip()
    if not cmd:continue
    phone.send(cmd.encode(utf-8))
    res=phone.recv(1024)
    print(res.decode(gbk))
phone.close()

注意注意注意:

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

的结果的编码是以当前所在的系统为准的,如果是windows,那么res.stdout.read()读出的就是GBK编码的,在接收端需要用GBK解码,且只能从管道里读一次结果。

struct模块

struct.unpack(fmt, buffer)struct.unpack做的工作刚好与struct.pack相反,用于将字节流转换成python数据类型。它的函数原型为:struct.unpack(fmt, string),该函数返回一个tuple。

 

subprocess、struct

标签:文件   class   函数返回   pop   str   hash   utf-8   提取   .so   

原文地址:http://www.cnblogs.com/jassin-du/p/7910378.html

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