热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

网络编程基础二

[TOC]subprocess模块?作用:?1、可以通过代码执行操作系统的终端命令?2、并返回终端执行命令后的结果TCP协议特性:是一个流式协议,会将多次连续发送的数据量小、间隔时


目录



  • subprocess模块

  • TCP协议

  • 黏包问题

  • 上传大文件

  • UDP

  • 简易聊天室

  • SocketServer




subprocess模块

? 作用:

? 1、可以通过代码执行操作系统的终端命令

? 2、并返回终端执行命令后的结果

用法:
import subprocess

cmd = inpu('CMD >>>')
obj = subprocess.Popen(
cmd.decode('utf8'),
shell=True,
stdout= subprocess.PIPE,
stderr= subprocess.PIPE
)
result = obj.stdout.read() + obj.stderr.read()

print(result.decode('gbk'))

TCP协议

特性:是一个流式协议,会将多次连续发送的数据量小、间隔时间短的数据一次性打包发送

黏包问题

? 原因:

? 1、无法预测需要接收的数据的长度

? 2、多次连续发送数据量小、并且时间间隔短的数据一次性打包发送。

解决黏包问题: 告诉对端数据的确切长度。

-struct模块:

? 必须先发送报头,再发送数据:

? 1、自定义报头,将数据长度等数据的描述信息制作成字典,

? 2、将字典json.dumps序列化并编码转为bytes,用于传输

? 3、先将报头的长度,用struct.pack格式化成固定长度(4字节)

? 4、发送:先发送报头长度,再发送报头,然后发送数据正文

? 接收:

? 1、先接收到4个字节的报头长度信息,unpack解压得到报头的长度值

? 2、根据报头长度值接收报头,解码并json.load反序列得到数据正文的描述信息(包含数据长度)

? 3、根据数据长度接收数据正文,

? 用法:

import json,struct
#假设通过客户端上传10G:10000000的文件:小视频.txt
#为避免粘包,必须自定制报头
header={'file_size':10000000,'file_name':'小视频.txt', 'md5':'8f6fbf8347faa4924a76856701edb0f3'} #10G数据,文件路径和md5值
#为了该报头能传送,需要序列化并且转为bytes
head_bytes=bytes(json.dumps(header),encoding='utf-8') #序列化并转成bytes,用于传输
#为了让客户端知道报头的长度,用struck将报头长度这个数字转成固定长度:4个字节
head_len_bytes=struct.pack('i',len(head_bytes)) #这4个字节里只包含了一个数字,该数字是报头的长度
#客户端开始发送
conn.send(head_len_bytes) #先发报头的长度,4个bytes
conn.send(head_bytes) #再发报头的字节格式
conn.sendall(文件内容) #然后发真实内容的字节格式
#服务端开始接收
head_len_bytes=s.recv(4) #先收报头4个bytes,得到报头长度的字节格式
x=struct.unpack('i',head_len_bytes)[0] #提取报头的长度
head_bytes=s.recv(x) #按照报头长度x,收取报头的bytes格式
header=json.loads(json.dumps(header)) #提取报头
#最后根据报头的内容提取真实的数据,比如
real_data_len=s.recv(header['file_size'])
s.recv(real_data_len)

上传大文件

以上传视频为例:

客户端:

import socket
import struct
import json
client = socket.socket()
client.connect(
('127.0.0.1', 9527)
)
with open(r'C:\day 027\5 上传大文件.mp4', 'rb')as f:
movie_bytes = f.read()
head_dic = {
'file_name': '5 上传大文件.mp4',
'file_size': len(movie_bytes)
}
json_head = json.dumps(head_dic)
bytes_head = json_head.encode('utf-8')
headers = struct.pack('i', len(bytes_head))
client.send(headers)
client.send(bytes_head)
init_data = 0
num = 1
with open(r'C:\day 027\5 上传大文件.mp4', 'rb')as f:
while init_data send_data = f.read(1024)
num += 1
client.send(send_data)
print(send_data, f'第{num}段数据发送完成')
init_data += len(send_data)
print('发送完毕!')

服务端:

import socket
import json
import struct
server = socket.socket()
server.bind(
('127.0.0.1', 9527)
)
server.listen(5)
while True:
conn, addr = server.accept()
try:
headers = conn.recv(4)
head_len = struct.unpack('i', headers)[0]
byte_head = conn.recv(head_len)
head_dic = json.loads(byte_head.decode('utf-8'))
print(head_dic)
file_name = head_dic.get('file_name')
file_size = head_dic.get('file_size')
init_data = 0
num = 1
with open(file_name, 'wb') as f:
while init_data data = conn.recv(1024)
print(f'第{num}段',data)
f.write(data)
init_data += len(data)
print(f'{file_name}接收完毕!')
except Exception as e:
print('error:', e)
break
conn.close()

UDP

? UDP是一种传输协议

? 1、不需要建立双向管道

? 2、不会黏包

? 3、客户端给服务端发送数据,不需要等服务端的回执

? 4、服务端只接收需要接收的数据,不管客户端传过来多少

服务端:

import socket
server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(
('127.0.0.1', 9527)
)
msg1 = server.recvfrom(1024)
msg2 = server.recvfrom(1024)
msg3 = server.recvfrom(1024)
print(msg1, msg2, msg3)

客户端:

import socket
client =socket.socket(type=socket.SOCK_DGRAM)
server_ip_port = ('127.0.0.1', 9527)
client.sendto(b'hello!', server_ip_port)
client.sendto(b'hello!', server_ip_port)
client.sendto(b'hello!', server_ip_port)
client.sendto(b'hello!', server_ip_port)
client.sendto(b'hello!', server_ip_port)

执行结果:(b‘hello!‘, (‘127.0.0.1‘, 57182)) (b‘hello!‘, (‘127.0.0.1‘, 57182)) (b‘hello!‘, (‘127.0.0.1‘, 57182))

简易聊天室

基于TCP协议,用socket套接字实现一个服务端对多个客户端的简易聊天室:

服务端:

import socket
server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(
('127.0.0.1', 9527)
)
while True:
# 服务端接收客户端传过来的消息
msg, addr = server.recvfrom(1024) # (消息,客户端地址)
msg1, addr1 = server.recvfrom(1024) # (消息,客户端地址)
msg2, addr2 = server.recvfrom(1024) # (消息,客户端地址)
print(addr)
print(addr1)
print(addr2)
print(msg.decode('utf-8'))
print(msg1.decode('utf-8'))
print(msg2.decode('utf-8'))
# 服务端往客户端发送消息
send_msg = input('服务端发送消息:').encode('utf-8')
server.sendto(send_msg, addr)
server.sendto(send_msg, addr1)
server.sendto(send_msg, addr2)

客户端1:

import socket
client = socket.socket(type=socket.SOCK_DGRAM)
server_ip_port = ('127.0.0.1', 9527)
while True:
send_msg = input('客户端1: ').encode('utf-8')
# 发送消息必须要加上对方地址
client.sendto(send_msg, server_ip_port)
# 能接收任何人的消息
msg = client.recv(1024)
print(msg.decode('utf-8'))

客户端2:

import socket
client = socket.socket(type=socket.SOCK_DGRAM)
server_ip_port = ('127.0.0.1', 9527)
while True:
send_msg = input('客户端2: ').encode('utf-8')
# 发送消息必须要加上对方地址
client.sendto(send_msg, server_ip_port)
# 能接收任何人的消息
msg = client.recv(1024)
print(msg.decode('utf-8'))

客户端3:

import socket
client = socket.socket(type=socket.SOCK_DGRAM)
server_ip_port = ('127.0.0.1', 9527)
while True:
send_msg = input('客户端3: ').encode('utf-8')
# 发送消息必须要加上对方地址
client.sendto(send_msg, server_ip_port)
# 能接收任何人的消息
msg = client.recv(1024)
print(msg.decode('utf-8'))

先启动服务端,再依次启动客户端,可开始模拟聊天室聊天

SocketServer

? 是python内置模块,可以用来简化socket套接字服务端的代码

import socket
class MyTcpServer(socketserver, BaseRequestHandler):
def handler(self):

data = self.request.recv(1024)
pirnt(data)
send_msg = input('服务端:').encode('utf8')
self.request.send(send_msg)


推荐阅读
  • 利用Selenium框架解决SSO单点登录接口无法返回Token的问题
    针对接口自动化测试中遇到的SSO单点登录系统不支持通过API接口返回Token的问题,本文提供了一种解决方案,即通过UI自动化工具Selenium模拟用户登录过程,从浏览器的localStorage或sessionStorage中提取Token。 ... [详细]
  • 本文深入探讨了锚点技术的应用与实现,通过十个关键点帮助读者全面理解锚点在网页设计中的作用。 ... [详细]
  • 拖拉切割直线 ... [详细]
  • 本文面向非计算机专业背景的编程爱好者,介绍如何仅使用基础的C语言知识——二维数组和结构体,无需掌握复杂的数据结构如链表,即可编写一款经典的贪食蛇游戏。通过本教程,您将了解游戏开发的基本原理和实现方法。 ... [详细]
  • Python中调用Java代码的方法与实践
    本文探讨了如何在Python环境中集成并调用Java代码,通过具体的步骤和示例展示了这一过程的技术细节。适合对跨语言编程感兴趣的开发者阅读。 ... [详细]
  • 本文讨论了在处理分页数据时常见的低级错误,并提供了优化后的代码示例,以减少重复代码并提高可读性和维护性。 ... [详细]
  • 本题要求根据给定的正整数数组,通过合理排列各元素顺序,生成并输出所有可能组合中的最小值。例如,对于数组{3, 32, 321},正确的输出应为321323。 ... [详细]
  • 本文介绍了DOM中用于获取节点信息的关键属性,包括父节点、子节点列表、首个及末个子节点、相邻兄弟节点以及节点类型等,同时提供了每个属性的具体使用说明。 ... [详细]
  • 端到端自动化测试框架设计 - 以京东商品搜索为例的Web应用测试
    本文将对前文介绍的京东商品搜索功能的端到端自动化测试进行总结,涵盖使用WebStorm、Node.js、Mocha、WebDriverIO及Selenium构建的测试环境,并特别讨论了如何通过会话保持用户登录状态。 ... [详细]
  • 本文详细对比了MySQL中的InnoDB与MyISAM两种存储引擎,从性能、事务处理能力、锁机制等多个维度进行了深入探讨,旨在为数据库设计者提供选择依据。 ... [详细]
  • 本文介绍了在Android Studio中通过代码和配置文件两种方法来移除Activity的标题栏,并讨论了当Activity继承自AppCompatActivity时的特殊处理方法。 ... [详细]
  • 本周六上午11点左右到达公司,回顾了一周的行业动态并完成了昨日的任务。下午主要解决了Axis2缓存问题以及DBS和KMS的相关技术难题。由于服务替换导致平台访问错误,经过多方查找未能解决,最终决定暂时搁置。此外,还分享了与朋友之间的沟通障碍及个人成长的思考。 ... [详细]
  • Pandas中使用sort_values方法进行数据排序
    本文介绍了如何利用Python的Pandas库中的sort_values方法对DataFrame对象进行排序。首先通过Numpy库生成随机数据,然后详细解释了DataFrame的创建过程及其参数,并重点探讨了sort_values方法的使用技巧。 ... [详细]
  • Python与Java在Appium中的应用:混合APP自动化测试方法详解
    本文详细探讨了如何使用Python和Java语言结合Appium框架进行混合APP的自动化测试,特别针对面试中常见的问题进行了整理和解答。 ... [详细]
  • 13、单向链表
    头文件:LinkList.hLinkList.cmain.cVS2 ... [详细]
author-avatar
亦涵Doris
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有