iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >31_网络编程-struct
  • 391
分享到

31_网络编程-struct

网络编程struct 2023-01-30 22:01:31 391人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

一、struct     1、简述    我们可以借助一个模块,这个模块可以把要发送的数据长度转换成固定长度的字节。这样客户端每次接收消息之前只要先接受这个固定长度字节的内容看一看接下来要接收的信息大小,那么最终接受的数据只要达到这个值就

一、struct
 
  1、简述
   我们可以借助一个模块,这个模块可以把要发送的数据长度转换成固定长度的字节。这样客户端每次接收消息之前只要先接受这个固定长度字节的内容看一看接下来要接收的信息大小,那么最终接受的数据只要达到这个值就停止,就能刚好不多不少的接收完整的数据了。
  该模块可以把一个类型,如数字,转成固定长度的bytes
1 >>> struct.pack('i',1111111111111)
2 struct.error: 'i' fORMat requires -2147483648 <= number <= 2147483647 #这个是范围
 

 

 1 import JSON,struct
 2 #假设通过客户端上传1T:1073741824000的文件a.txt
 3 
 4 #为避免粘包,必须自定制报头
 5 header={'file_size':1073741824000,'file_name':'/a/b/c/d/e/a.txt','md5':'8f6fbf8347faa4924a76856701edb0f3'} #1T数据,文件路径和md5值
 6 
 7 #为了该报头能传送,需要序列化并且转为bytes
 8 head_bytes=bytes(json.dumps(header),encoding='utf-8') #序列化并转成bytes,用于传输
 9 
10 #为了让客户端知道报头的长度,用struck将报头长度这个数字转成固定长度:4个字节
11 head_len_bytes=struct.pack('i',len(head_bytes)) #这4个字节里只包含了一个数字,该数字是报头的长度
12 
13 #客户端开始发送
14 conn.send(head_len_bytes) #先发报头的长度,4个bytes
15 conn.send(head_bytes) #再发报头的字节格式
16 conn.sendall(文件内容) #然后发真实内容的字节格式
17 
18 #服务端开始接收
19 head_len_bytes=s.recv(4) #先收报头4个bytes,得到报头长度的字节格式
20 x=struct.unpack('i',head_len_bytes)[0] #提取报头的长度,解包出来是元组
21 
22 head_bytes=s.recv(x) #按照报头长度x,收取报头的bytes格式
23 header=json.loads(json.dumps(header)) #提取报头
24 
25 #最后根据报头的内容提取真实的数据,比如
26 real_data_len=s.recv(header['file_size'])
27 s.recv(real_data_len)
View Code

 

  2、struct解决黏包问题
  借助struct模块,我们知道长度数字可以被转换成一个标准大小的4字节数字。因此可以利用这个特点来预先发送数据长度。
 
发送时 接收时
先发送struct转换好的数据长度4字节 先接受4个字节使用struct转换成数字来获取要接收的数据长度
再发送数据 再按照长度接收数据
  
 
  服务端
 1 import Socket
 2 import subprocess
 3 import struct
 4 
 5 server = socket.socket()
 6 ip_port = ('192.168.15.113',8001)
 7 server.bind(ip_port)
 8 server.listen()
 9 conn,addr = server.accept()
10 while 1:
11     #来自客户端的指令
12     print('等待接受信息。。。')
13     from_client_cmd = conn.recv(1024).decode('utf-8')
14     print(from_client_cmd)
15     #通过subprocess模块执行服务端的系统指令,并且拿到指令执行结果
16     sub_obj = subprocess.Popen(
17         from_client_cmd, #客户端的指令
18         shell=True,
19         stdout=subprocess.PIPE, #标准输出:正确指令的执行结果在这里
20         stderr=subprocess.PIPE, #标准错误输出:错误指令的执行结果在这里
21     )
22     #接受到的返回信息是bytes类型的,并且windows系统的默认编码为gbk
23     server_cmd_msg = sub_obj.stdout.read()
24     # server_cmd_err = sub_obj.stderr.read().decode('gbk')
25     #首先计算出你将要发送的数据的长度
26     cmd_msg_len = len(server_cmd_msg)
27     #先对数据长度进行打包,打包成4个字节的数据,目的是为了和你将要发送的数据拼在一起,就好我们自定制了一个消息头
28     msg_len_stru = struct.pack('i',cmd_msg_len)
29     conn.send(msg_len_stru) #首先发送打包成功后的那4个字节的数据
30     conn.sendall(server_cmd_msg) #循环send数据,直到数据全部发送成功
server

 

  客户端

 1 import socket
 2 import struct
 3 client = socket.socket()
 4 server_ip_port = ('192.168.15.113',8001)
 5 client.connect(server_ip_port)
 6 while 1:
 7     msg = input('请输入要执行的指令>>>')
 8     client.send(msg.encode('utf-8'))
 9     #先接收服务端要发送给我的信息的长度,前4个字节,固定的
10     from_server_msglen = client.recv(4)
11     unpack_len_msg = struct.unpack('i',from_server_msglen)[0]
12     #接收数据长度统计,和服务端发给我的数据长度作比较,来确定跳出循环的条件
13     recv_msg_len = 0
14     #统计拼接接收到的数据,注意:这个不是统计长度
15     all_msg = b''
16     while recv_msg_len < unpack_len_msg:
17         every_recv_data = client.recv(1024)
18         #将每次接收的数据进行拼接和统计
19         all_msg += every_recv_data
20         #对每次接收到的数据的长度进行累加
21         recv_msg_len += len(every_recv_data)
22 
23     print(all_msg.decode('gbk'))
client

 

  复杂的服务端(自定义报头)

 1 import socket,struct,json
 2 import subprocess
 3 phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
 4 phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
 5 
 6 phone.bind(('127.0.0.1',8080))
 7 phone.listen(5)
 8 
 9 while True:
10     conn,addr=phone.accept()
11     while True:
12         cmd=conn.recv(1024)
13         if not cmd:break
14         print('cmd: %s' %cmd)
15 
16         res=subprocess.Popen(cmd.decode('utf-8'),
17                              shell=True,
18                              stdout=subprocess.PIPE,
19                              stderr=subprocess.PIPE)
20         err=res.stderr.read()
21         print(err)
22         if err:
23             back_msg=err
24         else:
25             back_msg=res.stdout.read()
26 
27         headers={'data_size':len(back_msg)}
28         head_json=json.dumps(headers)
29         head_json_bytes=bytes(head_json,encoding='utf-8')
30 
31         conn.send(struct.pack('i',len(head_json_bytes))) #先发报头的长度
32         conn.send(head_json_bytes) #再发报头
33         conn.sendall(back_msg) #在发真实的内容
34 
35     conn.close()
View Code
 
 1 from socket import *
 2 import struct,json
 3 
 4 ip_port=('127.0.0.1',8080)
 5 client=socket(AF_INET,SOCK_STREAM)
 6 client.connect(ip_port)
 7 
 8 while True:
 9     cmd=input('>>: ')
10     if not cmd:continue
11     client.send(bytes(cmd,encoding='utf-8'))
12 
13     head=client.recv(4)
14     head_json_len=struct.unpack('i',head)[0]
15     head_json=json.loads(client.recv(head_json_len).decode('utf-8'))
16     data_len=head_json['data_size']
17 
18     recv_size=0
19     recv_data=b''
20     while recv_size < data_len:
21         recv_data+=client.recv(1024)
22         recv_size+=len(recv_data)
23 
24     #print(recv_data.decode('utf-8'))
25     print(recv_data.decode('gbk')) #windows默认gbk编码
26 
27 tcp_client.py
View Code

 

  head = {'file name': 'test', 'filesize': 8192, 'filetype': 'txt', 'filepath': r'\user\bin'}
  报头长度       ——>         先接收4字节
  send(head) 报头   ——>        根据这4个字节获取报头
  send(file)    报文  ——>     从报头中获取filesize,然后根据filesize接收文件
  整个流程的大致解释:
  我们可以把报头做成字典,字典里包含将要发送的真实数据的描述信息(大小啊之类的),然后json序列化,然后用struck将序列化后的数据长度打包成4个字节。
  我们在网络上传输的所有数据 都叫做数据包,数据包里的所有数据都叫做报文,报文里面不止有你的数据,还有ip地址、Mac地址、端口号等等,其实所有的报文都有报头,这个报头是协议规定的,看一下
 
  发送时:
  先发报头长度
  再编码报头内容然后发送
  最后发真实内容
 
  接收时:
  先手报头长度,用struct取出来
  根据取出的长度收取报头内容,然后解码,反序列化
  从反序列化的结果中取出待取数据的描述信息,然后去取真实的数据内容

--结束END--

本文标题: 31_网络编程-struct

本文链接: https://www.lsjlt.com/news/180079.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 31_网络编程-struct
    一、struct     1、简述    我们可以借助一个模块,这个模块可以把要发送的数据长度转换成固定长度的字节。这样客户端每次接收消息之前只要先接受这个固定长度字节的内容看一看接下来要接收的信息大小,那么最终接受的数据只要达到这个值就...
    99+
    2023-01-30
    网络编程 struct
  • 网络编程
    1. 网络编程入门 1.1 网络编程概述 计算机网络 是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统 网络编程...
    99+
    2023-08-30
    网络 Java
  • Java网络编程 - 网络编程介绍 - 网络通信三要素
    文章目录 网络编程网络编程介绍网络通信三要素要素一: IP地址IP地址基本介绍IP地址的操作类 要素二: 端口号要素三: 协议TCP协议UDP协议 网络编程 网络...
    99+
    2023-09-07
    网络 java 网络协议
  • python网络编程-socket编程
    一、服务端和客户端 BS架构 (腾讯通软件:server+client) CS架构 (web网站)   C/S架构与socket的关系: 我们学习socket就是为了完成C/S架构的开发   二、OSI七层模型 互联网协议按照功能不同分为...
    99+
    2023-01-31
    网络编程 python socket
  • Java 网络编程
    Java 网络编程   目录 Java 网络编程   Socket 编程 ServerSocket 类的方法 Socket 类的方法   InetAddress 类的方法 Socket 客户端实例 Socket 服务端实例     网络编...
    99+
    2023-10-09
    java
  • 网络编程—udp
    一、ip地址 1. 什么是地址 地址就是用来标记地点的   2. ip地址的作用 ip地址:用来在网络中标记一台电脑,比如192.168.1.1;在本地局域网上是唯一的。   3. ip地址的分类 每一个IP地址包括两部分:网络地址和主机...
    99+
    2023-01-31
    网络编程 udp
  • 网络编程—tcp
              一、TCP简介           二、tcp网络程序-客户端           三、tcp网络程序-服务器           四、案例:文件下载器           五、tcp三次握手、四次挥手        ...
    99+
    2023-01-31
    网络编程 tcp
  • Android网络编程
    Android网络编程目录小朋友你是不是有很多问号???一、网页源码查看器二、消息机制的写法(重点)1、相关概念2、Handler的使用3、消息...
    99+
    2022-06-06
    Android
  • Python网络编程
    # notes 要点网络编程 客户端/服务器架构 客户端/服务器网络编程 套接字是计算机网络数据结构。在任何类型的通信开始之前,网络应用程序必须创建套接字。可以将它们比作电话插孔,没有它将无法进行通信。 进程间通信(Inter Proc...
    99+
    2023-01-31
    网络编程 Python
  • 网络编程(全)
    【网络编程】 今日内容 软件架构CS/BS网络通信三要素TCP通信Socket套接字ServerSocket文件上传自定义服务器 第一章 网络编程入门 1.1软件结构 C/S结构 :全称为Client...
    99+
    2023-09-06
    网络 tcp/ip 服务器
  • Python 网络编程
    Python 网络编程 Python 提供了两个级别访问的网络服务: 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统 Socket 接口的全部方法。 高级别的网络服务模块 S...
    99+
    2023-08-31
    网络 服务器 运维
  • 【网络编程】网络编程 和 Socket 套接字认识
    ✨个人主页:bit me👇 ✨当前专栏:Java EE初阶👇 目 录 🎧一. 网络编程基础🎺1. 为什么需要网络编程?🎷2....
    99+
    2023-08-23
    网络 服务器 java
  • C#网络编程之Socket编程
    目录一:什么是SOCKET套接字分类二:SOCKET相关概念1、端口2、协议2.1 TCP:2.2 UDP三:socket一般应用模式:四:SOCKET通信基本流程图:服务器端:客户...
    99+
    2022-11-13
  • 网络编程(详细)
    文章目录 网络编程的概念网络模型OSI 七层模型七层模型释义通信特点 TCP/IP 五层模型区别 网络编程的目的网络编程中的两个要素 IP 地址IP 地址类型IP 地址 `J...
    99+
    2023-09-13
    网络 服务器 网络协议
  • 初始网络编程
    专栏简介: JavaEE从入门到进阶 题目来源: leetcode,牛客,剑指offer. 创作目标: 记录学习JavaEE学习历程 希望在提升自己的同时,帮助他人,,与大家一起共同进步,互相成长. 学历代表过去,能力代表现...
    99+
    2023-09-13
    网络协议 网络编程
  • 初识网络编程
    c/s b/s 架构client 客户端/server 服务端browser 浏览器/server 服务端现在多数都是客户端与服务端之间进行交互,获取信息但像微信小程序,支付宝等一些应用都开始发展小程序功能,通过微信就可直接在内部调用其他...
    99+
    2023-01-31
    网络编程
  • pythonnet-网络编程(1)
    python的网络编程有不少难点,也容易忘记,最近我会陆续发出系统、完整pythonnet知识的博客,一边复习一边分享,感兴趣的可以关注我。 话不多说,开始吧。   网络编程 目的:数据的传输 ISO(国际标准化组织) OSI七层模型--...
    99+
    2023-01-30
    网络编程 pythonnet
  • python网络编程--socket
    1.服务端1.1声明socket对象server=socket.socket(AF.INET,socket.SOCK_STREAM)1.2绑定ip、端口server.bind(localhost,6969)1.3开始监听server.lis...
    99+
    2023-01-31
    网络编程 python socket
  • python网络编程(一)
    python网络编程想使用python体验下多简单,于是写了最简单的一个C/S程序,的确实现起来很简单!服务器端程序:#!/usr/bin/pythonimport socketlistensock=socket.socket(socket...
    99+
    2023-01-31
    网络编程 python
  • Python—网络编程Socket
    Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数...
    99+
    2023-01-31
    网络编程 Python Socket
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作