python 并发编程(socketserver)
下面的例子是简单的ssh 登录,其实也就是客户端把指令发送给服务器。服务器把结果返还给客户端,客户端再在终端展现 服务端代码:
#Author:BigBao
#Date:2018/7/18
# 我们之前没有实现并发的原因是,我们之前是链接循环加通信循环,我们只有建立连接后才能通信,通信的过程中腾不出手来建立连接
# 所以现在我们得把链接循环和通信循环给分开,一个class一直在建立连接,一个class一直在通信
# 我们之前的是我们必须创建过链接之后立马去通信,通过过程中部可以去建立连接
'''
socketserver
封装了多进程,多线程
同时还封装了多路复用,把我们的程序性能发挥到机制
'''
import socketserver
import subprocess
import json
import struct
# 通信循环
class MyTcpHandler(socketserver.BaseRequestHandler): # BaseRequestHandler 专门用来负责处理通信相关信息的
def handle(self): # 这里必须定义一个handle方法,而且方法名必须是handle, sockerserver 会自动去调用handle这个方法
print(self.request) # 这里的self.request 相当于我们之前看到的conn那个对象( conn,client_addr=server.accept() )
while True:
try:
recv_cliend_cmd = self.request.recv(1024) #接收客户端的指令
if not recv_cliend_cmd:break
# 下面就要对客户端发送的指令进行处理了
obj=subprocess.Popen(recv_cliend_cmd.decode('utf-8'),shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout = obj.stdout.read()
stderr = obj.stderr.read()
# 下面开始创建报头(随意写的),这里我们真正用到的就是字典里的total_size
header_dic={
'total_size':len(stdout)+len(stderr),
'filename':'xxx.mp4',
'md5sum':'8f6fbf8347faa4924a76856701edb0f3'
}
header_json = json.dumps(header_dic)
header_bytes = header_json.encode('utf-8')
self.request.send(struct.pack('i',len(header_bytes))) # 这个发送过去为固定的字节数 4 个,所以客户端第一次接收四个字节即可 self.request.send(header_bytes) self.request.send(stdout)
self.request.send(stderr) except ConnectionResetError:break
self.request.close() # 连接循环
if __name__ == '__main__':
server = socketserver.ThreadingTCPServer(('127.0.0.1',8080),MyTcpHandler) #基于Tcp的多线程服务端
server.serve_forever()
# 客户端发来请求,就建立一个连接,server 立马造一个线程,然后再把MyTcpHandler 类实例化得到一个对象,触发对象下面的handle方法,把连接丢给 handle 方法(handle方法下的self.request 就是建立的连接)
# 也就是说客户端来一个连接,建立后就会触发通信循环的的handle 方法,我们可以看一下self.request 打印出来的东西就是本地IP:端口 客户端IP:端口
客户端代码 #Author:BigBao
#Date:2018/7/18
import socket
import struct
import json
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(('127.0.0.1',8080))
while True:
cmd = input('please input your cmd: ').strip()
if not cmd:continue
client.send(cmd.encode('utf-8'))
obj = client.recv(4)
header_size = struct.unpack('i',obj)[0]
header_bytes = client.recv(header_size)
header_json = header_bytes.decode('utf-8')
header_dic = json.loads(header_json)
total_size = header_dic['total_size']
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()
我们上面处理的黏包问题是发生在服务端发数据给客户端,客户端的数据接收不完全的解决方案。要是涉及到两边都有黏包问题的话,解决方案也是上面一样解决
python 并发编程(socketserver)的更多相关文章
- Python并发编程-SocketServer多线程版
#server.py import socket from threading import Thread def chat(conn): conn.send(b'hello') msg = conn ...
- Python并发编程理论篇
Python并发编程理论篇 前言 其实关于Python的并发编程是比较难写的一章,因为涉及到的知识很复杂并且理论偏多,所以在这里我尽量的用一些非常简明的语言来尽可能的将它描述清楚,在学习之前首先要记住 ...
- Python并发编程__多进程
Python并发编程_多进程 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大 ...
- Python并发编程的几篇文章
Python几种并发实现方案的性能比较 http://www.elias.cn/Python/PyConcurrency?from=Develop.PyConcurrency python并发编程 h ...
- Python并发编程之深入理解yield from语法(八)
大家好,并发编程 进入第八篇. 直到上一篇,我们终于迎来了Python并发编程中,最高级.最重要.当然也是最难的知识点--协程. 当你看到这一篇的时候,请确保你对生成器的知识,有一定的了解.当然不了解 ...
- 自学Python之路-Python并发编程+数据库+前端
自学Python之路-Python并发编程+数据库+前端 自学Python之路[第一回]:1.11.2 1.3
- Python并发编程二(多线程、协程、IO模型)
1.python并发编程之多线程(理论) 1.1线程概念 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程(流水线的工作需要电源,电源就相当于 ...
- Python并发编程一(多进程)
1.背景知识(进程.多道技术) 顾名思义,进程即正在执行的一个过程.进程是对正在运行程序的一个抽象. 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一 ...
- 《转载》Python并发编程之线程池/进程池--concurrent.futures模块
本文转载自Python并发编程之线程池/进程池--concurrent.futures模块 一.关于concurrent.futures模块 Python标准库为我们提供了threading和mult ...
- Python并发编程系列之多线程
1 引言 上一篇博文详细总结了Python进程的用法,这一篇博文来所以说Python中线程的用法.实际上,程序的运行都是以线程为基本单位的,每一个进程中都至少有一个线程(主线程),线程又可以创建子线程 ...
随机推荐
- windows安装python2.7后的注册(registry)问题
[提要]win平台上,python2.7官网的安装包在安装后不会添加环境变量且不会把安装信息写入注册表. 把python和pip的安装路径添加到环境变量是做python开发必要的一步,而写入注册表的原 ...
- sudo 和环境变量
https://askubuntu.com/questions/57915/environment-variables-when-run-with-sudo https://www.phusionpa ...
- The cast to value type 'System.Decimal' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.
CurrentStock = db.BillEntry.Where(b => b.GoodsId == item.GoodsId).Sum(b => (decimal?)b.Qty) ?? ...
- jqPlot图表插件学习之数据节点高亮和光标提示
一.准备工作 首先我们需要到官网下载所需的文件: 官网下载(笔者选择的是jquery.jqplot.1.0.8r1250.zip这个版本) 然后读者需要根据自己的情况新建一个项目并且按照如下的方式加载 ...
- AJAX的同步返回结果值
function makeJQGridDataFromList(url) { var rowData; var viewPage = 0; var viewTotal = 0; ...
- 修改mysql数据引擎的方法- 提高数据库性能
前言:同学告我说,他为了能使得数据查询变得快一点,修改的数据引擎,故查询一下,总结一下. 登录mysql后,查看当前数据库支持的引擎和默认的数据库引擎,使用下面命令: mysql>show en ...
- C#代码优化—字符串拼接效率比较
字符串拼接主要有以下几种方法: + : 加号 String.Format() : 字符串格式化 StringBuilder.Append() 说明 对于少量固定的字符串拼接,如string str = ...
- 推荐系统 BPR 算法求解过程
数据假设: 每个用户之间的偏好行为相互独立 同一用户对不同物品的偏序相互独立 则优化问题为极大化如下目标: [Reference] 1.论文翻译:BPR:面向隐偏好数据的贝叶斯个性化排序学习模型 2. ...
- Lua编程笔记
迭代器并没有真正的迭代,真正迭代的是for循环.而迭代器为每次迭代提供成功后的返回值. function allwords(f)for line in io.lines do for word in ...
- 深度优化LNMP之PHP
PHP缓存加速介绍 1.操作码介绍及缓存原理 当客户端请求一个php程序时,服务器的PHP引擎会解析该PHP程序,并将其编译为特定的操作码文件(Operate Code,opcode)该文 ...