基于tcp协议的套接字通信:远程执行命令
要解决粘包问题:
TCP:流式协议
特点:
1、数据流没有开头也没有结果,像水流一样
2、TCP协议有一个nagle算法,
nagle算法会将数据量较小,并且时间间隔较短的数据合成一条数据发送,
这么做可以减少网络IO次数,进而提升传输效率
1.struct模块
#1、把整型数字转成bytes类型
#2、转成的bytes是固定长度的 import struct
import json header_dic = {
'total_size': 31222222222121,
'md5': '123svsaef123sdfasdf',
'filename': 'a.txt'
} #序列化:内存中的数据结构----》转成一种中间格式(字符串)----》存到文件中
header_json=json.dumps(header_dic)
print(header_json,type(header_json)) #编码:编码后的结果为bytes类型
header_bytes=header_json.encode('utf-8')
header_size=len(header_bytes)
print(header_size) # #打包
obj=struct.pack('i',header_size)
print(obj,len(obj)) # b'Q\x00\x00\x00' 4 #解包
obj2=struct.unpack('i',obj)
print(obj2) # (81,)
打印结果:
{"total_size": 31222222222121, "md5": "123svsaef123sdfasdf", "filename": "a.txt"} <class 'str'>
81
b'Q\x00\x00\x00' 4
(81,)
result
2.通讯整个流程:
'''
流程:
服务端:制作报头,把报头信息丢到报头字典里,字典序列化得到json字符串,encode得到bytes
---->发报头长度(struct.pack打成4个bytes)--->发送报头---->发真实数据 客户端:先接收4个bytes:struct.unpack解包报头长度--->接收报头-->
解析报头:decode得到字符串,反序列化得到报头--->根据报头内的信息,收取真实的数据 '''
3.具体代码如下:
服务端:
from socket import *
import subprocess
import struct
import json server=socket(AF_INET,SOCK_STREAM)
server.bind(('127.0.0.1',8080))
server.listen(5) #半连接池:限制的是请求数,而不是连接数 while True:
conn,client_addr=server.accept() #(连接对象,客户端的ip和端口) conn:tcp三次握手的一个产物,可以用来收发消息
print(client_addr) #此处client_addr的作用是可以知道哪个客户端建的链接,和通讯无关
while True:
try:
cmd=conn.recv(1024) #cmd为bytes类型,
obj=subprocess.Popen(cmd.decode('utf-8'),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
stdout=obj.stdout.read() #拿到系统执行的结果(subprocess执行的是window系统命令,解码需要gbk)
stderr=obj.stderr.read() # 1、制作报头
header_dic={
'total_size':len(stdout) + len(stderr),
'md5':'123svsaef123sdfasdf',
'filename':'a.txt'
}
header_json = json.dumps(header_dic) #json序列化报头
header_bytes = header_json.encode('utf-8') #字符串类型---->bytes类型,发送 # 2、先发送报头的长度
header_size=len(header_bytes)
conn.send(struct.pack('i',header_size)) # 3、发送报头
conn.send(header_bytes) # 4、发送真实的数据
conn.send(stdout) #send只能发bytes类型
conn.send(stderr)
except ConnectionResetError:
break
conn.close()
server.close()
客户端:
from socket import *
import struct
import json client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8080))
# print(client) while True:
cmd=input('>>>: ').strip()
if not cmd:continue
client.send(cmd.encode('utf-8')) #把命令结果发给服务器
#1、先收报头的长度根据报头内的信息,收取真实的数据
header_size=struct.unpack('i',client.recv(4))[0] #bytes类型,想拿到报头长度要对bytes进行解出 #2、接收报头
header_bytes=client.recv(header_size) #对应服务端的发送报头 #3、解析报头
header_json=header_bytes.decode('utf-8') #bytes类型---->字符串类型
header_dic=json.loads(header_json) #反序列化拿到报头
print(header_dic) total_size=header_dic[ 'total_size']
# print(total_size) #1025
#4、接收数据 recv_size=0
res=b''
while recv_size < total_size:
recv_data=client.recv(1024)
res+=recv_data
recv_size+=len(recv_data) print(res.decode('gbk'))
client.close()
基于tcp协议的套接字通信:远程执行命令的更多相关文章
- python 之 网络编程(基于TCP协议的套接字通信操作)
第八章网络编程 8.1 基于TCP协议的套接字通信 服务端套接字函数 s.bind() 绑定(主机,端口号)到套接字 s.listen() 开始TCP监听 s.accept() 被动接受TCP客户的连 ...
- 什么是 socket?简述基于 tcp 协议的套接字通信流程?
Socket的英文原义是"孔"或"插座".通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄, 可以用来实现不同虚拟机或不同计 ...
- 网络编程----socket介绍、基于tcp协议的套接字实现、基于udp协议的套接字实现
一.客户端/服务器架构(C/S架构) 即C/S架构,包括: 1.硬件C/S架构(打印机) 2.软件C/S架 ...
- 网络编程(二)--TCP协议、基于tcp协议的套接字socket
一.TCP协议(Transmission Control Protocol 传输控制协议) 1.可靠传输,TCP数据包没有长度限制,理论上可以无限长,但是为了保证网络的效率,通常TCP数据包的长度不会 ...
- 网络编程之TCP三次握手与四次挥手、基于TCP协议的套接字编程
目录 TCP三次握手和四次挥手 背景描述 常用的熟知端口号 TCP概述 TCP连接的建立(三次握手) TCP四次挥手 如果已建立连接,客户端突然断开,会怎么办呢? 基于TCP协议的套接字编程 什么是S ...
- 网络编程(二)——TCP协议、基于tcp协议的套接字socket
TCP协议与基于tcp协议的套接字socket 一.TCP协议(流式协议) 1.可靠传输,TCP数据包没有长度限制,理论上可以无限长,但是为了保证网络的效率,通常TCP数据包的长度不会超过IP数据包的 ...
- [网络编程之Socket套接字介绍,套接字工作流程,基于TCP协议的套接字程序]
[网络编程之Socket套接字介绍,套接字工作流程,基于TCP协议的套接字程序] 为何学习socket套接字一定要先学习互联网协议: 1.首先:要想开发一款自己的C/S架构软件,就必须掌握socket ...
- python 之 网络编程(基于UDP协议的套接字通信)
8.5 基于UDP协议的套接字通信 UDP协议:数据报协议 特点:无连接,一发对应一收,先启动哪一端都不会报错 优点:发送效率高,但有效传输的数据量最多为500bytes 缺点:不可靠:发送数据,无需 ...
- 基于TCP_socket套接字实现远程执行命令
基于tcp的套接字实现远程执行命令的操作 ——客户端敲命令,服务端执行 #服务端 import socket import subprocess phone=socket.socket(socket. ...
随机推荐
- Jmeter接口测试实战之HTTP Cookie管理器(十二 )
在使用测试工具Jmeter做接口测试中,怎么记录下它登录成功后的信息,在接口测试的应用场景中,一般对业务的操作都是基于用户登录情况下的操作.它的测试步骤相对来说很简单的,其实在Jmeter的测试工具中 ...
- Ubuntu添加新用户并给普通用户赋予root新权限
添加新用户 首先用adduser命令添加普通用户: #adduser newusername 只有在root权限才可以添加新用户 修改密码: #passwd username 赋予root权限 方法1 ...
- [vijos1782]借教室<线段树>
题目链接:https://vijos.org/p/1782 题意:一个区间1,n.m次操作,每次操作让l,r区间值减去d,当有任何一个值小于0就输出当前是第几个操作 这道题其实是没有什么难度的,是 ...
- 【WPF学习】第六十二章 构建更复杂的模板
在控件模板和为其提供支持的代码之间又一个隐含约定.如果使用自定义控件模板替代控件的标准模板,就需要确保新模板能够满足控件的实现代码的所有需要. 在简单控件中,这个过程比较容易,因为对模板几乎没有(或完 ...
- Blazor入门笔记(3)-C#与JS交互
1.环境 VS2019 16.5.1 .NET Core SDK 3.1.200 Blazor WebAssembly Templates 3.2.0-preview2.20160.5 2.前言 Bl ...
- 当阿里面试官问我:Java创建线程有几种方式?我就知道问题没那么简单
这是最新的大厂面试系列,还原真实场景,提炼出知识点分享给大家. 点赞再看,养成习惯~ 微信搜索[武哥聊编程],关注这个 Java 菜鸟. 昨天有个小伙伴去阿里面试实习生岗位,面试官问他了一个老生常谈的 ...
- Spark Streaming 编程入门指南
Spark Streaming 是核心Spark API的扩展,可实现实时数据流的可伸缩,高吞吐量,容错流处理.可以从许多数据源(例如Kafka,Flume,Kinesis或TCP sockets)中 ...
- 为什么MySQL要用B+树?聊聊B+树与硬盘的前世今生【宇哥带你玩转MySQL 索引篇(二)】
为什么MySQL要用B+树?聊聊B+树与硬盘的前世今生 在上一节,我们聊到数据库为了让我们的查询加速,通过索引方式对数据进行冗余并排序,这样我们在使用时就可以在排好序的数据里进行快速的二分查找,使得查 ...
- 如何在云开发静态托管中使用Jekyll
如何在云开发静态托管中使用Jekyll 介绍 Jekyll 是一个简单的博客形态的静态站点生产机器,通过它,我们可以搭建一个完整的可发布的静态博客网站. Jekyll 也可以运行在 GitHub Pa ...
- pgsql中的行锁
pgsql中的行锁 前言 用户可见的锁 regular Lock 行级别 FOR UPDATE FOR NO KEY UPDATE FOR SHARE FOR KEY SHARE 测试下加锁之后的数据 ...