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 不可靠的,无连接的服务,传送效率高
随机推荐
- Git使用(一)
声明: 第一次使用git,只能保证我的方法可以用,肯定不是最简最好的.以后需要用到更多的用法的时候再来这里更新. 说实话,记下来主要是因为自己记性不好,各种配置记不住,都是当备忘录用的,(囧囧囧囧囧) ...
- 剑指offer——27. 二叉搜索树与双向链表(Java版)
题目: 剑指offer的题目有挺多都挺典型的,就像这一道.不过书中的代码写的真是ugly,有很多题目LeetCode上都有,可以去LeetCode讨论区看看,经常有一些大神分享,写的代码真是高效.简洁 ...
- windows 平台下 安装解密 openssl
1 在openssl 官网下载 openssl 安装, 本机是 64位 win 8.1 系统 http://slproweb.com/products/Win32OpenSSL.html 下载:Win ...
- C#4.0 System.Dynamic
System.Dynamic 命名空间提供支持动态语言运行时的类和接口. 代码下载地址:GitHub 本篇主要讲两个类:①ExpandoObject ②DynamicObject (重点) ①E ...
- Spring知识点总结(四)之SpringAOP基础
1. Spring aop中的基本概念 • 连接点(Joinpoint):在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候.在Spring AOP中,一个连接 ...
- SpringMVC 导入导出Excel文件
/** * 下载Excel模板 创建一个新的文件用于下载,创建的文件放在缓存中 * * @param request * @param response */ /* * @Request ...
- java中泛型的简单使用
泛型是在jdk1.5之后引入的,我们可以在类的声明处增加泛型列表,如:<T,E,V>.此处,字符可以是任何标识符,一般采用这3个字母. 1.泛型类声明 class MyCollection ...
- java8新特性学习2
六.Stream API Java8中有两大最为重要的改变.第一个是 Lambda 表达式:另外一个则是 Stream API(java.util.stream.*).Stream 是 Java8 中 ...
- 移动设备HTML5页面布局
在HTML5标准添加的新元素中,用于常见页面结 构的包括header footer footer nav aside aside article section hgroup . 下面简单介绍一下这个 ...
- 车站分级 (2013noip普及组T4)(树形DP)
题目描述 一条单向的铁路线上,依次有编号为 1,2,…,n 的 n个火车站.每个火车站都有一个级别,最低为 1 级.现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车站 x ...