Python学习笔记八
类的高级用法
多态:
在其他语言,使用的是类的继承。
在python中,不需要指定数据类型。
基于TCP协议的socket通信实现:
类似于打电话的情景。
服务端:
1.买手机
2.插卡
3.开机
4.等待电话链接
5.收消息
6.发消息
7.挂电话
8.关手机
具体代码实现如下:
import socket #导入一个socket模块
server1=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机,基于socket的网络通信,使用的是TCP协议
server1.bind(('127.0.0.1',8080)) #插卡,指定服务器的IP地址和端口号
server1.listen(5) #开机,设置监听等待数
conn,client_addr=server1.accept() #等待电话链接
while True:
recv_data=conn.recv(1024) #收消息,限制单个消息的最大数为1024字节
print(recv_data)
conn.send(recv_data.upper()) #发消息 conn.close() #挂手机
server1.close() #关机
客户端:
1.买手机
2.打电话
3.发消息
4.收消息
具体代码实现:
import socket
client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(('127.0.0.1',8080)) #打电话 while True:
message=input('数据>>').strip()
client.send(message.encode('utf-8')) #发消息
recv=client.recv(1024) #收消息
print(recv)
上面的服务端和客户端都添加了while True,实现了通信循环。
但是现在有个问题:就是如果客户端输入为空,客户端会卡住。
分析这个问题:
要么就是客户端没有发送出去,要么就是客户端没有收到。
结果:因为客户端发送为空的消息,但是服务器并没有收到该消息,所以客户端也不会收到空消息,所以会被卡住。
所以需要在客户端上设置,用户不可以发送为空的消息。
修改后的代码:
import socket
client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(('127.0.0.1',8080)) #打电话 while True:
message=input('数据>>').strip()
if not message:continue
client.send(message.encode('utf-8')) #发消息
recv=client.recv(1024) #收消息
print(recv)
加上链接循环:
import socket #导入一个socket模块
server1=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机,基于socket的网络通信,使用的是TCP协议
server1.bind(('127.0.0.1',8080)) #插卡,指定服务器的IP地址和端口号
server1.listen(5) #开机,设置监听等待数
while True:
conn,client_addr=server1.accept() #等待电话链接
while True:
try:
recv_data=conn.recv(1024) #收消息,限制单个消息的最大数为1024字节
if not recv_date:break
print(recv_data)
conn.send(recv_data.upper()) #发消息
except ConnectionResetError:
break
conn.close() #挂手机
server1.close() #关机
前提是:客户端单方面断开链接
如果服务端是windows系统,就添加一个try错误处理,如果服务端是linux,就不会有异常,服务端一直在接受空,所以需要加一个判断,如果为空就退出通信循环
命令的结果:如何获取
os.system('命令'): 这种方法只是执行了一下命令,并返回一个值。可以通过这个值,判断命令是否执行成功。
subprocess.Popen('命令',shell=True):这个方法是执行的结果是内存地址。它可以指定执行的结果放到某个位置。
subprocess.Popen('命令',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
import subprocess
res=subprocess.Popen('dir',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
res_stdout=res.stdout.read()
res_stderr=res.stderr.read()
print(res_stdout.decode('gbk'))
res_stdout1=res.stdout.read()
print('jieguo',res_stdout1.decode('gbk'))
#管道读取一次以后,管道就为空了。因为取走了。
结果如下:
C:\Users\yangjianbo\AppData\Local\Programs\Python\Python36\python.exe C:/Users/yangjianbo/PycharmProjects/untitled/第八课面向对象高级/subprocess模块.py
驱动器 C 中的卷是 Windows
卷的序列号是 58DC-A9CB
C:\Users\yangjianbo\PycharmProjects\untitled\第八课面向对象高级 的目录
2017/11/08 22:10 <DIR> .
2017/11/08 22:10 <DIR> ..
2017/11/05 12:25 19 b.py
2017/11/08 21:35 355 socket客户端.py
2017/11/08 21:35 764 socket服务器.py
2017/11/08 22:10 417 subprocess模块.py
2017/11/05 12:10 0 __init__.py
2017/11/08 21:50 <DIR> __pycache__
2017/11/07 23:32 352 客户端2.py
2017/11/07 23:32 352 客户端3.py
2017/11/07 23:32 352 客户端4.py
2017/11/07 23:32 352 客户端5.py
2017/11/07 23:32 352 客户端6.py
2017/11/07 23:34 352 客户端7.py
11 个文件 3,667 字节
3 个目录 458,471,485,440 可用字节
第二次读取管道的命令结果==========》
可以看到结果:第一次的结果是正确执行命令后的结果,第二次的命令执行结果就为空了。
命令执行错误的结果,会放到stderr的管道中。
import subprocess
res=subprocess.Popen('啊啊啊',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
res_stdout=res.stdout.read()
res_stderr=res.stderr.read()
print(res_stdout.decode('gbk'))
res_stdout1=res.stdout.read()
print('第二次读取管道的命令结果==========》',res_stdout1.decode('gbk'))
print(res_stderr.decode('gbk'))
结果:
C:\Users\yangjianbo\AppData\Local\Programs\Python\Python36\python.exe C:/Users/yangjianbo/PycharmProjects/untitled/第八课面向对象高级/subprocess模块.py
第二次读取管道的命令结果==========》
'啊啊啊' 不是内部或外部命令,也不是可运行的程序
或批处理文件。
stdin参数:用来把第一个命令执行的结果输入到第二个命令中。
简单SSH程序:
服务端代码:
import socket #导入一个socket模块
import subprocess
server1=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机,基于socket的网络通信,使用的是TCP协议
server1.bind(('127.0.0.1',8080)) #插卡,指定服务器的IP地址和端口号
server1.listen(5) #开机,设置监听等待数
while True:
conn,client_addr=server1.accept() #等待电话链接
while True:
try:
cmd=conn.recv(1024) #收消息,限制单个消息的最大数为1024字节
if not cmd :break
cmd=cmd.decode('utf-8')
cmd_res=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
stdout_res=cmd_res.stdout.read()
stderr_res=cmd_res.stderr.read() # 返回的结果就是bytes类型,所以不需要再decode了。
conn.send(stdout_res+stderr_res) #发消息
except ConnectionResetError:
break
conn.close() #挂手机
server1.close() #关机
客户端代码:
import socket
client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(('127.0.0.1',8080)) #打电话 while True:
cmd=input('数据>>').strip()
if not cmd:continue
client.send(cmd.encode('utf-8')) #发消息
recv=client.recv(1024).decode('gbk') #收消息 因为输出在windows系统下,所以客户端的编码应该为gbk.
print(recv) client.close()
关于SSH远程程序执行cd命令的问题:
以一个变量为标准,当执行cd命令的时候,把这个变量的值加上你要切换的目录,这才是整个完整的路径。
关于SSH远程程序执行top命令的问题:
时时刷新top命令,其实是服务端在定期刷新一下,返回结果给客户端。不可能实现实时刷新的效果,肯定是在定期刷新的。
1024: 收包的大小限制,最大为1024字节。只是限制收消息的大小。这个值最大设置为8096,再大就没有必要了。
解决方法:
把客户端接收的包大小调大,但是这种方法不合适,因为无法预测服务端返回的结果大小。
而且收到的数据都存放在内存中,太消耗资源了。
TCP粘包现象:
TCP为了避免网络中的大量小包,会使用一个nagle算法,将包粘在一起发送。数据量小,时间间隔小,TCP会发生粘包现象。
为了解决粘包的问题,协议会采用一种固定的方式:报头+数据
struct模块:
把数字转换成bytes类型。
struct.pack('i',后面的数字) i代表打包后的结果是4个bytes,打包的数字就是整型数字。
struct.unpack('i',后面的数字)
最终版:
制作报头
header_dic={}
序列化:
打包报头
把报头大小打包成固定长度。
Python学习笔记八的更多相关文章
- python学习笔记(八)-模块
大型python程序以模块和包的形式组织.python标准库中包含大量的模块.一个python文件就是一个模块.1.标准模块 python自带的,不需要你安装的2.第三方模块 需要安装,别人提供的. ...
- python 学习笔记八 进程和线程 (进阶篇)
什么是线程(thread)? 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执 ...
- python学习笔记八--动态类型
一.变量,对象,引用: 1. 变量: 2. 对象:均包含了一个头部信息,有以下两部分内容 a.对象的数据类型, b.引用计数器:纪录当前引用货指向该对象的数量,一旦计数器被清零,该对象的内存空间就会被 ...
- python学习笔记(八)、特殊方法、特性和迭代器
1 新式类和旧式类 python类的工作方式在不断变化.较新的Python2版本有两种类,其中旧式类正快速退出舞台.新式类时Python2.2 引入的,提供了一些额外功能,如支持函数super 和 p ...
- python学习笔记八——字典的方法
4.3.3 字典的方法 字典的常用方法可以极大地提高编程效率.keys()和values()分别返回字典的key列表和value列表.例: dict={"a":"appl ...
- Python学习笔记八:ORM框架SQLAlchemy
一:SQLAlchemy使用 1:实体类的创建 ORM中的实体类与一般的Python类不同,在其中,使用 __tablename__=""指明该类与数据库中某个表相对应,然后定义一 ...
- Python学习笔记八:文件操作(续),文件编码与解码,函数,递归,函数式编程介绍,高阶函数
文件操作(续) 获得文件句柄位置,f.tell(),从0开始,按字符数计数 f.read(5),读取5个字符 返回文件句柄到某位置,f.seek(0) 文件在编辑过程中改变编码,f.detech() ...
- python学习笔记八:文件与目录
一.文件的打开和创建 1.打开 open(file,mode): >>>fo = open('test.txt', 'r') >>>fo.read() 'hello ...
- python学习笔记八(集合)
集合 set是一个无序的不重复元素序列. 用大括号或set()函数创建集合.注意:创建一个空集合用set(),不用{},{}用来创建空字典 basket = {'apple','orange','ap ...
随机推荐
- kettle变量(param命名参数)
1.定义: 编辑-设置-命名参数 在当前界面下定义参数名称和缺省值. 2.引用:原始数据 通过${var}引用变量 输出 注:1.字符串在命名参数引用是需要添加单引号的,但位置参数是不需要进行转译: ...
- 转 spring注解式参数校验
转自: https://blog.csdn.net/jinzhencs/article/details/51682830 转自: https://blog.csdn.net/zalan01408980 ...
- Java垃圾收集器概述
垃圾收集器的操作 查找未使用的对象,释放内存,并压缩堆,避免内存碎片 一个java程序,有执行应用程序逻辑的线程和执行GC的线程组.当GC跟踪对象引用,或在内存中移动对象,它必须确保应用程序线程没有使 ...
- Atcoder Beginner Contest 124 解题报告
心态爆炸.本来能全做出来的.但是由于双开了Comet oj一个比赛,写了ABC就去搞那个的B题 还被搞死了. 回来写了一会D就过了.可惜比赛已经结束了.真的是作死. A - Buttons #incl ...
- thymeleaf 页面获取当前页面的完整URL地址
下面两种方法是一样的 <div th:text="${#httpServletRequest.getRequestURL() +'?'+ #httpServletRequest.get ...
- Linux(Ubuntu)换apt-get源
在虚拟机安装完Ubuntu后,因为apt-get命令默认的服务器在国外会很慢,换成国内的会快很多 选一个国内镜像源,以清华大学开源镜像为例,要选对应的Ubuntu版本 网站链接https://mirr ...
- mysql日志分析工具之mysqlsla
背景介绍: 很多情况下,都需要对MySQL日志进行各种分析,来了解系统运行的方方面面.MySQL官方自带了一些工具对日志进行分析,比如mysqlbinlog可以用来分析二进制日志,mysqlslow可 ...
- DaishaPocedureOfMine(代码)
create procedure GetGoodsInfoByPageNumber ( @provideID int, @pageNumber int, @GoodsCountOfOnePage fl ...
- Vue(小案例_vue+axios仿手机app)_go实现退回上一个路由
一.前言 this.$router.go(-1)返回上级路由 二.主要内容 1.小功能演示: 2.组件之间的嵌套关系为: 3.具体实现 (1)由于这种返回按钮在每个页面中的结构都是一样的,只是里面的数 ...
- python4 分支结构,循环结构 for循环
## 复习 ```python'''1.变量名命名规范 -- 1.只能由数字.字母 及 _ 组成 -- 2.不能以数字开头 -- 3.不能与系统关键字重名 -- 4._开头有特殊含义 -- 5.__开 ...