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中线程的用法.实际上,程序的运行都是以线程为基本单位的,每一个进程中都至少有一个线程(主线程),线程又可以创建子线程 ...
随机推荐
- Grunt、Gulp和Webpack对比
1.Grunt处理Sass转换成CSS过程 2.Gulp处理Sass转换成CSS过程 3.Webpack执行原理 4.区别 (1)grunt和gulp都类似于webapck的中的scripts,属于任 ...
- How do I fix a “Unknown configuration key `foreign-architecture' found in your `dpkg' configuration files.” error?
My /etc/dpkg/dpkg.cfg.d/multiarch contained: foreign-architecture i386 I deleted the file. I then is ...
- NDK编译常用命令及不同版本so编译方法
工具说明 addr2line 把程序地址转换为文件名和行号.在命令行中给它一个地址和一个可执行文件名,它就会使用这个可执行文件的调试信息指出在给出的地址上是哪个文件以及行号. ar 建立.修改.提取归 ...
- java 生成二维码后叠加LOGO并转换成base64
1.代码 见文末推荐 2.测试 测试1:生成base64码 public static void main(String[] args) throws Exception { String dat ...
- python之docstrinigs
# -*- coding: cp936 -*- #python 27 #xiaodeng #docstrinigs #文档字符串惯例 ''' 1.多行字符串 2.首行以大写字母开始,以句号结束 3.第 ...
- 【转】IP地址、子网掩码、网络号、主机号、网络地址、主机地址以及ip段
背景知识 IP地址 IP地址被用来当做Internet上的电脑的身份编号.大家日常见到的情况是每台联网的PC上都需要有IP地址,才能正常通信.我们可以把“个人电脑”比作“一台电话”,那么“IP地址”就 ...
- 设置cnblogs默认滚动条样式
默认滚动条样式丑嘛就不谈了~这里修改为个性化滚动条样式. CSS代码 /*滚动条整体样式*/ body::-webkit-scrollbar { width: 10px; height: 1px; } ...
- SqlServer安装时的选项说明
转自:https://blog.csdn.net/m0_37154839/article/details/80233446 看看组件的功能说明吧 服务器组件 说明 SQL Server 数据库引擎 S ...
- linux shell 脚本攻略学习13--file命令详解,diff命令详解
一.file命令详解 find命令可以通过查看文件内容来找出特定类型的文件,在UNIX/ Linux系统中,文件类型并不是由文件扩展名来决定的(windows中却正是这么做的),file命令的目的是从 ...
- 一台电脑存放多个git账户的多个rsa秘钥(转)
如何在一个电脑上存储多个git账户生成的多份rsa秘钥,实现多个账户同时使用配置的情况?今天,不幸又再次遇到这个问题. 问题描述 公司最近在开发一款开源产品,项目被托管在github上,但是公司内部一 ...