python 网络编程(远程执行命令与粘包)
远程执行命令
先来学习一个新模块 , 一会用到的..
新模块: subprocess
执行系统命令
r = subprocess.Popen('ls',shell=True,stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
subprocess.Popen(a,b,c,d)
a: 要执行的系统命令(str)
b: shell = True 表示确定我当前执行的命令为系统命令
c: 表示正确信息的输出管道
d: 表示错误信息的输出管道
下边直接上代码,一看就懂. TCP的
import socket
import subprocess
sk = socket.socket()
sk.bind(('127.0.0.1',9090))
sk.listen()
conn,addr = sk.accept()
while 1:
cmd = conn.recv(1024).decode('utf-8')
res = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
std_out = res.stdout.read()# 读取正确的返回信息
std_err = res.stderr.read()# 读取错误的返回信息 if std_out:
conn.send(std_out)
else:
conn.send(std_err) conn.close()
sk.close()
远程服务端
import socket
sk = socket.socket()
sk.connect_ex(('127.0.0.1',9090))
while 1:
cmd = input('请输入一个命令>>>')
sk.send(cmd.encode('utf-8'))
print(sk.recv(204800000).decode('gbk')) sk.close()
远程客户端
就是引用了一个模块的功能,其他的还是简单的收发功能.
res=subprocess.Popen(cmd.decode('utf-8'),
shell=True,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE)
的结果的编码是以当前所在的系统为准的,如果是windows,那么res.stdout.read()读出的就是GBK编码的,在接收端需要用GBK解码
且只能从管道里读一次结果
注意
--------------------粘包---------------------------


UDP不会发生黏包--------
UDP(user datagram protocol,用户数据报协议)是无连接的,面向消息的,提供高效率服务。
不会使用块的合并优化算法,, 由于UDP支持的是一对多的模式,所以接收端的skbuff(套接字缓冲区)采用了链式结构来记录每一个到达的UDP包,
在每个UDP包中就有了消息头(消息来源地址,端口等信息),这样,对于接收端来说,就容易进行区分处理了。
即面向消息的通信是有消息保护边界的。
对于空消息:tcp是基于数据流的,于是收发的消息不能为空,这就需要在客户端和服务端都添加空消息的处理机制,防止程序卡住,
而udp是基于数据报的,即便是你输入的是空内容(直接回车),也可以被发送,udp协议会帮你封装上消息头发送过去。
不可靠不黏包的udp协议:udp的recvfrom是阻塞的,一个recvfrom(x)必须对唯一一个sendinto(y),收完了x个字节的数据就算完成,若是y;x数据就丢失,
这意味着udp根本不会粘包,但是会丢数据,不可靠。
补充说明:
用UDP协议发送时,用sendto函数最大能发送数据的长度为:65535- IP头(20) – UDP头(8)=65507字节。
用sendto函数发送数据时,如果发送数据长度大于该值,则函数会返回错误。(丢弃这个包,不进行发送) 用TCP协议发送时,由于TCP是数据流协议,因此不存在包大小的限制(暂不考虑缓冲区的大小),这是指在用send函数时,数据长度参数不受限制。
而实际上,所指定的这段数据并不一定会一次性发送出去,如果这段数据比较长,会被分段发送,如果比较短,可能会等待和下一次数据一起发送。
总结
黏包现象只发生在tcp协议中:
1.从表面上看,黏包问题主要是因为发送方和接收方的缓存机制、tcp协议面向流通信的特点。
2.实际上,主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的
解决方案------------
我们可以借助一个模块,这个模块可以把要发送的数据长度转换成固定长度的字节。这样客户端每次接收消息之前只要先接受这个固定长度字节的内容看一看接下来要接收的信息大小,那么最终接受的数据只要达到这个值就停止,就能刚好不多不少的接收完整的数据了。

文件上传解决粘包 的代码: 利用字典先传过去文件大小即可....
import socket
import json
import struct
sk = socket.socket()
sk.bind(('127.0.0.1',9090))
sk.listen()
conn,addr = sk.accept()
dic_size = conn.recv(4)# 先接受4字节长度的一个bytes, 代表字典的大小
dic_size = struct.unpack('i',dic_size)[0]# 将这个特殊的bytes转变成原数字
dic_str = conn.recv(dic_size).decode('utf-8')# 根据字典大小去获取字典,以免和底下获取文件内容发生粘包
dic = json.loads(dic_str)# 反序列化 得到字典 opt filename filesize
if dic['opt'] == 'upload':
'''接收文件'''
filename = ''+dic['filename']# 将文件名字修改,防止重名
with open(filename,'wb') as f:
while dic['filesize']:
content = conn.recv(1024)
f.write(content)
dic['filesize'] -= len(content)
elif dic['opt'] == 'download':
'''给客户端传输文件'''
conn.close()
sk.close()
文件上传 服务端
import socket
import os
import json import struct sk = socket.socket()
sk.connect(('127.0.0.1',9090))
l = ['upload','download']
for i,v in enumerate(l):
print(i+1,v)
dic = {'opt':None,'filename':None,'filesize':None}
while 1:
opt = input("请输入功能选项>>>")# 客户要执行的操作选项
if opt == '':
'''upload'''
file_dir = input('请输入文件路径>>>')# 'E:/sylar/python_workspace/day34/作业/时间同步机制_client.py'
file_name = os.path.basename(file_dir)# 获取文件名字
file_size = os.path.getsize(file_dir)# 获取文件大小
dic['opt'] = l[int(opt)-1]
dic['filename'] = file_name
dic['filesize'] = file_size
dic_str = json.dumps(dic)# 将字典序列化成一个字符串形式的字典
dic_size = len(dic_str)# 获取字典的大小
ds = struct.pack('i',dic_size)# 把一个小于21.3E的一个数字转变成一个4字节长度的bytes
sk.send(ds + dic_str.encode('utf-8'))# 发送给服务器
with open(file_dir,'rb') as f:
while file_size:
content = f.read(1024)# 文件内容
sk.send(content)
file_size -= len(content)
elif opt == '':
'''download'''
pass
else:
print('有误') sk.close()
文件上传 客户端

收发概括

python 网络编程(远程执行命令与粘包)的更多相关文章
- 网络编程之模拟ssh远程执行命令、粘包问题 、解决粘包问题
		
目录 模拟ssh远程执行命令 服务端 客户端 粘包问题 什么是粘包 TCP发送数据的四种情况 粘包的两种情况 解决粘包问题 struct模块 解决粘包问题 服务端 客户端 模拟ssh远程执行命令 服务 ...
 - Python_编写UDP通信编解码类、文件的上传、远程执行命令、黏包
		
1.UDP通信编解码类 (1) 类 # ------------------UDP通信解码编码类------------------------ from socket import * class ...
 - python之paramiko 远程执行命令
		
有时会需要在远程的机器上执行一个命令,并获得其返回结果.对于这种情况,python 可以很容易的实现. 1 .工具 Python paramiko 1) Paramiko模块安装 在Linux的Ter ...
 - Python 简单的远程执行命令
		
client端执行命令,server端返回命令结果 # server 端 import socket, subprocess sk = socket.socket() address=('127.0. ...
 - python实现批量远程执行命令及批量上传下载文件
		
#!/usr/bin/env python # -*- coding: utf- -*- # @Time : // : # @Author : xuxuedong # @Site : # @File ...
 - 【游戏开发】网络编程之浅谈TCP粘包、拆包问题及其解决方案
		
引子 现如今手游开发中网络编程是必不可少的重要一环,如果使用的是TCP协议的话,那么不可避免的就会遇见TCP粘包和拆包的问题,马三觉得haifeiWu博主的 TCP 粘包问题浅析及其解决方案 这篇博客 ...
 - TCP 远程执行CMD (解决粘包问题) 代码
		
服务端 from socket import * import subprocess,json,struct server= socket(AF_INET,SOCK_STREAM) server.bi ...
 - Python网络编程基础   struct模块 解决黏包问题 FTP
		
struct模块 解决黏包问题 FTP
 - 网络编程socket模块subprocess模块 粘包的解决
		
什么是socket? tcp 可靠地面向连接协议 udp 不可靠的,无连接的服务,传送效率高
 
随机推荐
- gcc扩展语法一:在表达式中的语句和声明
			
在GNU C中包含在括号中的复合语句可以作为一个表达式.这就允许你在表达式中使用循环,switch和局部变量. 以前复合语句是包含在大括号中语句序列.在这种构造中,圆括号包围在大括号中.如下面的例子: ...
 - SpringBoot非官方教程 | 第十二篇:springboot集成apidoc
			
转载请标明出处: 原文首发于:https://www.fangzhipeng.com/springboot/2017/07/11/springboot-apidoc/ 本文出自方志朋的博客 首先声明下 ...
 - [UNIX]UNIX常用命令总结
			
(1)查看服务器IP信息 $netstat -in (2)查看挂载磁盘信息 #sam #需要在root账号下查看
 - IntelliJ IDEA使用hibernate
			
环境:数据库:mariadb 10.2.16 https://downloads.mariadb.org/配置好maven:见收藏的博文链接 https://www.cnblogs.com/ICE_ ...
 - SQL里的concat() 以及group_concat() 函数的使用
			
实例参考:https://blog.csdn.net/mary19920410/article/details/76545053 一 concat()函数 1.功能:将多个字符串连接成一个字符串. 2 ...
 - Swift 中关于”??”操作符
			
Swift 中关于”??”操作符 Swift 的语法在保证安全和健壮的基础上,又带有很多非常灵活的特性,比如 ?? 操作符就是其中一个.大家可能已经了解它,也可能有些同学不了解它,这里给大家整理了关于 ...
 - 初涉基环外向树dp&&bzoj1040: [ZJOI2008]骑士
			
基环外向树dp竟然如此简单…… Description Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发 ...
 - ABAP术语-Method
			
Method 原文:http://www.cnblogs.com/qiangsheng/archive/2008/03/05/1091077.html Component of classes in ...
 - mysql 使用 FIND_IN_SET 来查询数据
			
mysql中find_in_set函数很有意思,它的功能是查找以英文逗号隔开的值,我们可以将数据存储类似为1,2,3,4格式.今天我们就来看看在thinkphp中怎样正确地使用find_in_set函 ...
 - javascript--事件对象e的来源、意义、应用及其属性的用法     function(e){}
			
在类似于arcgis api for javascript中,经常会遇到function(e),以前一直不懂e是个什么玩意,这种写法啥意思,经过最近一段时间学习,对e有了很深了解,本文通过各种示例,由 ...