subprocess、struct

要点:

  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。

时间: 2024-09-20 06:52:14

subprocess、struct的相关文章

Linux C/C++ 区别:类型声明、struct

C有数组.结构体.指针.函数.宏 C++有命名空间.引用.默认参数.模板.函数重载.自定义操作符.内联.构造/析构.私有/保护成员.友元.异常. 一.数据类型的声明 1. C++允许数据声明出现在程序的任意位置 C代码(异常) 1 #include <stdlib.h> 2 #include <stdio.h> 3 4 int main(int argc, char* argv[]) 5 { 6 for(int i=0; i<5; i++) 7 printf("he

Swift学习之enum、struct、class的异同详解

由于在开发过程中常常需要用到系统提供的基础类型之外的的类型,因此Swift开发中我们可以根据自己的需要构建属于自己的类型系统以便于更加灵活和方便的开发程序并将其称之为named types.Swift主要为我们提供了以下四种named types 分别是:enum.struct.class和protocol, 相信熟悉objective-c开发的同学们对于iOS中枚举.结构体和类的概念一点都不陌生.相比于前辈objective-c中的这三者,Swift将enum和struct变得更加灵活且强大,

class、interface、struct的区别

1 struct和class有什么区别 1.1默认的继承访问权限 Struct是public的,class是private的. 你可以写如下的代码: struct A { char a; }; struct B:A { char b; } 这个时候B是public继承A的.如果都将上面的struct改成class,那么B是private继承A的.这就是默认时的继承访问权限.所以我们在平时写类继承的时候,通常会这样写: struct B:public A 就是为了指明是public继承,而不是用默

比较两个slice、struct或者map是否相等

我们可以直接使用reflect.DeepEqual来比较两个slice.struct或者map是否相等 package main import ( "fmt" "reflect" ) type A struct { s string } func main() { a1 := A{s: "abc"} a2 := A{s: "abc"} if reflect.DeepEqual(a1, a2) { fmt.Println(a1,

C# byte[]、struct、intptr等的相互转换

1.struct byte[]互相转换 //struct转换为byte[] public static byte[] StructToBytes(object structObj) { int size = Marshal.SizeOf(structObj); IntPtr buffer = Marshal.AllocHGlobal(size); try { Marshal.StructureToPtr(structObj, buffer, false); byte[] bytes = new

linux内核内存分配(二、struct slab和struct kmem_cache)

前一篇bloglinux内核内存分配(一.基本概念)主要是分析linux内核内存的分配和物理页分配函数接口.但是在实际的操作中,不一定所有内存申请都需要一个物理页,很多只是需要分配几K大小的内存就可以.所以就需要更小的内存分配函数.刚开始看这个有点不懂,不过懂了就很简单了.哈哈. slab思想 摘抄<深入linux设备驱动程序内核机制>的一段话:slab分配器的基本思想是,先利用页面分配器分配出单个或者一组连续的物理页面,然后在此基础上将整块页面分割成多个相等的小内存单元,以满足小内存空间分配

获取网络接口信息——ioctl()函数与结构体struct ifreq、 struct ifconf

转载请注明出处:windeal专栏 Linux 下 可以使用ioctl()函数 以及 结构体 struct ifreq  结构体struct ifconf来获取网络接口的各种信息. ioctl 首先看ioctl()用法 ioctl()原型如下: #include <sys/ioctl.h> int ioctl(int fd, int request, ...); 参数: fd     : 文件描述符 request:  表示要请求的信息.如IP地址.网络掩码等 ...     :  后面的可变

python模块之subprocess模块, struct模块

subprocess import subprocess ''' sh-3.2# ls /Users/egon/Desktop |grep txt$ mysql.txt tt.txt 事物.txt ''' res1=subprocess.Popen('ls /Users/jieli/Desktop',shell=True,stdout=subprocess.PIPE) res=subprocess.Popen('grep txt$',shell=True,stdin=res1.stdout, s

C++学习笔记(十四):public、private、struct、class

1.关于public和private的区别 在C++中,为了控制类的成员的访问和封装(隐藏),常使用public和private说明符来对类的成员进行封装. 定义在public说明符之后的成员在整个程序中可以被访问,public成员定义类的接口 定义在private说明符之后的成员可以被类的成员函数访问,但是不能被使用该类的代码访问,private部分封装(隐藏)了类的实现细节. 例如: struct  Sales_data{ public: Sales_data() = default;