02: SocketServer服务
网络编程其他篇
目录:
1.1 SocketServer四种基本流及 异步处理理论部分返回顶部
1、SocketServer作用
1. socket无法支持多并发,SocketServer 可以实现多并发
2. SocketServer使编写一个Socket服务器通信变得更加简单
3. SocketServer其实就是对socket的再封装
2、SocketServer提供了4个基本的服务类
1. TCPServer针对TCP套接字流
2. UDPServer针对UDP数据报套接字
3. UnixStreamServer和UnixDatagramServer针对UNIX域套接字,不常用(Unix本机间通信)
4. 它们的继承关系如下:
3、异步处理
1. 上面四个服务类都是同步处理请求的,一个请求没处理完不能处理下一个请求
2. 要想支持异步模型,可以利用多继承让server类继承ForkingMixIn 或 ThreadingMixIn mix-in classes。
3. ForkingMixIn利用多进程(分叉)实现异步。
4. ThreadingMixIn利用多线程实现异步。
4.、请求处理类
1. 要实现一项服务,还必须派生一个handler class请求处理类,并重写父类的handle()方法
2. handle方法就是用来专门是处理请求的,该模块是通过服务类和请求处理类组合来处理请求的。
3. SocketServer模块提供的请求处理类有BaseRequestHandler,以及它的派生类StreamRequestHandler和DatagramRequestHandler
4. 从名字看出可以一个处理流式套接字,一个处理数据报套接字。
5、实现异步,支持多连接
1. 前面介绍服务类时提到过,四个基本的服务类默认是同步模型的。
2. 要想支持异步可以利用多继承从ForkingMixIn 或ThreadingMixInmix-in classes和一个基本的服务类继承来定义一个支持异步的服务类
3. 比如:class Server(ThreadingMixIn, TCPServer): pass
4. ForkingMixIn 要考虑进程间的通信。ThreadingMixIn要考虑线程访问同一变量时的同步和互斥
1.2 创建socketserver实现: 多客户端并发返回顶部
1、创建一个socketserver 至少分以下几步
1. 创建一个request handler class(请求处理类),继承自BaseRequestHandler class并重写它的handle()方法,该方法将处理客户端的请求。
2. 实例化一个server class对象,并将服务的地址和之前创建的request handler class传递给它。
server class对象有这些:TCPServer;UDPServer;UnixStreamServer;UnixDatagramServer
3. 调用server class对象的handle_request() 或 serve_forever()方法来开始处理请求
4. handle_request和server_forever区别是server_forever只是反复handle_request而已
import socketserver
class MyTcpServer(socketserver.BaseRequestHandler):
def handle(self):
while True:
self.request.recv(1024)
self.request.send('I am server'.encode('utf-8'))
server = socketserver.ThreadingTCPServer(('127.0.0.1',8888),MyTcpServer)
server.serve_forever()
简化版的server端代码如下
import socketserver
#每个客户端过来都会实例化一个MyTCPHandler实例,并调用handle方法来处理与客户端的通信
class MyTCPHandler(socketserver.BaseRequestHandler):
#1 第一步:创建一个request handler class(请求处理类),继承自BaseRequestHandler class
def handle(self): #2 第二步:并重写它的handle()方法,该方法将处理客户端的请求
while True:
try:
self.data = self.request.recv(1024).strip() #conn.recv(1024) = self.request.recv()
print("{} wrote:".format(self.client_address[0]))
print(self.data)
self.request.send(self.data.upper()) #conn.send()=self.request.sendall()
except ConnectionResetError as e:
print("error",e)
break
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler) #socketserver.TCPServer(单)
server.serve_forever() #4 第四步:调用server class对象的serve_forever()方法来开始处理请求
#3 第三步:实例化一个server class对象,并将服务的地址和之前创建的request handler class传递给它
#注: 实例化一个server class对象工作原理
#a. (HOST, PORT):将监听地址当做一个参数传递给socketserver.TCPServer()
#b. 每连接一个客户端就用MyTCPHandler实例化一个对象,将实例对象传送给socketserver.TCPServer
#c. 然后服务器端使用MyTCPHandler类中的handle方法与客户端通信
socketserver实现多客户端并发: server端
import socket
client = socket.socket() #声明socket类型,同时生成socket连接对象
client.connect(('localhost',9999)) #指定要连接的服务器地址和端口号
while True:
msg = input(">>:").strip() #输入要发送给服务器的消息
if len(msg) == 0:continue #如果客户端输入空格,让客户端继续输入
client.send(msg.encode("utf-8")) #将输入的消息发送到服务器端
data = client.recv(1024) #接收服务器端发送过来的数据,每次1024字节
print('client_recv:',data) #将从服务器端接收的数据在客户端打印出来
client.close()
socketserver实现多客户端并发: client端
1.3 SocketServer实现多并发FTP 部分功能返回顶部
1、使用SocketServer完成FTP的多用户上传这个步骤
import socketserver,os,json #服务器端代码
class MyTCPHandler(socketserver.BaseRequestHandler):
def put(self,*args):
'''接收客户端文件'''
cmd_dic = args[0]
filename = cmd_dic["filename"]
filesize = cmd_dic["size"]
if os.path.isfile(filename):
f = open(filename + '.new','wb')
else:
f = open(filename,'wb')
print("file not exist",filename)
self.request.send(b"200 ok")
receive_size = 0
while receive_size < filesize:
data = self.request.recv(1024)
f.write(data)
receive_size += len(data)
else:
print("file [%s] hsa uploaded ..."%filename) def handle(self):
while True:
try:
self.data = self.request.recv(1024).strip()
print("{} wrote:".format(self.client_address[0]))
print(self.data)
cmd_dic = json.loads(self.data.decode())
action = cmd_dic["action"]
if hasattr(self,action):
func = getattr(self,action)
func(cmd_dic)
except ConnectionResetError as e:
print("error",e)
break
if __name__ == "__main__":
HOST, PORT = "0.0.0.0", 9999
server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
多用户上传: server端代码
import socket,os,json
class FtpClient(object):
def __init__(self):
self.client = socket.socket()
def help(self):
msg = '''ls; pwd; cd .. ;get filename ; put filename'''
print(msg)
def connect(self,ip,port):
self.client.connect((ip,port))
def interactive(self):
#self.authenticate()
while True:
cmd = input(">>:").strip()
if len(cmd) == 0:continue
cmd_str = cmd.split()[0]
if hasattr(self,'cmd_%s'%cmd_str):
func = getattr(self,'cmd_%s'%cmd_str)
func(cmd)
else:
self.help()
def cmd_put(self,*args):
cmd_split = args[0].split()
if len(cmd_split) > 1:
filename = cmd_split[1]
if os.path.isfile(filename):
filesize = os.stat(filename).st_size
msg_dic = {
"action": "put",
"filename":filename,
'size':filesize,
'overridden':True
}
self.client.send( json.dumps(msg_dic).encode('utf-8') )
server_response = self.client.recv(1024) #防止连包, 等服务器确认
f = open(filename,'rb')
for line in f:
self.client.send(line)
else:
print("file upload success.....")
f.close()
else:
print(filename,"is not exist")
def cmd_get(self):
pass
ftp = FtpClient()
ftp.connect("1.1.1.3",9999)
ftp.interactive()
多用户上传: client端代码
1、将server端代码复制到Linux下,路径:/bbb/server.py
2. 将client端代码直接放到PyCharm中运行
3. 在PyCharm中执行put tt.py将本目录下的tt.py文件上传到linux的/bbb文件夹中
>>:put tt.py
file upload success.....
4. 执行命令完成后就可以看到有这个文件:/bbb/tt.py
用户上传运行演示
2、文件传输时显示进度条
import sys,time
def view_bar(num, total):
rate = num / total
rate_num = int(rate * 100)
r = '\r[%s%s]%d%%' % ("="*num, " "*(100-num), rate_num, )
sys.stdout.write(r)
sys.stdout.flush() for i in range(0, 101):
time.sleep(0.1)
view_bar(i, 100) # 1)这里使用的是sys.stdout.write(r),输出结果是进度条增加,但是不会换行
# 2)2.x中的print无法指定end符号为其他值,默认会输出一个"\n",也就是用一次必定换到下一行
# 3)到了3.x中print成为了一个真正意义上的函数,后来就可以任意指定end符号的值,你可以输出一次后末尾添加上任意你想要的值,而不是强制换行。
# 4)stdout没有end这个符号这一说,输出不会换行,因此如果你想同一样输出多次,在需要输出的字符串对象里面加上"\r",就可以回到行首了。
打印进度条代码
02: SocketServer服务的更多相关文章
- 网络编程~~~~socketserver服务端
socketserver服务端 import socketserver class MyServer(socketserver.BaseRequestHandler): def handle(self ...
- JAVAEE——宜立方商城02:服务中间件dubbo、工程改造为基于soa架构、商品列表实现
1. 学习计划 第二天:商品列表功能实现 1.服务中间件dubbo 2.工程改造为基于soa架构 3.商品列表查询功能实现. 2. 将工程改造为SOA架构 2.1. 分析 由于宜立方商城是基于soa的 ...
- Spring Cloud开发实践 - 02 - Eureka服务和接口定义
服务注册 EurekaServer Eureka服务模块只有三个文件, 分别是pom.xml, application.yml 和 EurekaServerApplication.java, 内容如下 ...
- dubbo源码分析02:服务引用
一.何时创建服务引用 引用官方文档的原话,如果将Dubbo托管在Spring-IOC容器下,Dubbo服务引用的时机有两个,第一个是在Spring容器调用ReferenceBean的afterProp ...
- 「 从0到1学习微服务SpringCloud 」02 Eureka服务注册与发现
系列文章(更新ing): 「 从0到1学习微服务SpringCloud 」01 一起来学呀! Spring Cloud Eureka 基于Netflix Eureka做了二次封装(Spring Clo ...
- 【SpringCloud】02.微服务与SpringCloud
微服务的特点 一系列微小的服务共同组成 跑在自己的进程里 每个服务为独立的业务开发 独立部署 分布式管理 异构--不同的语言.不同类型的数据库 微服务架构的基础框架/组件 服务注册发现 服务网关(Se ...
- SSH服务详解
第1章 SSH服务 1.1 SSH服务协议说明 SSH 是 Secure Shell Protocol 的简写,由 IETF 网络工作小组(Network Working Group )制定:在进行数 ...
- 十一.keepalived高可用服务实践部署
期中集群架构-第十一章-keepalived高可用集群章节======================================================================0 ...
- 【原创】Windows服务管家婆之Service Control Manager
Service Control Manager,服务控制管理器,人称SCM就是它!在Windows内核中,都可以看到她忙碌的身影,可以说是系统服务和驱动的管家婆了! SCM管家婆起早贪黑,每次 ...
随机推荐
- oracle listagg函数、lag函数、lead函数 实例
Oracle大师Thomas Kyte在他的经典著作中,反复强调过一个实现需求方案选取顺序: “如果你可以使用一句SQL解决的需求,就使用一句SQL:如果不可以,就考虑PL/SQL是否可以:如果PL/ ...
- Git:上传GitHub项目操作步骤
git教程:git详解.gitbook #首次上传步骤 首先在工程文件位置处右键git bash here 本地创建ssh key $ ssh-keygen -t rsa -C "your_ ...
- Docker基本命令与使用 —— Dockerfile指令与构建(三)
一.Dockerfile指令上 1.指令格式 # Comment 注释, 以#开头 INSTRUCTION argument 以大写的指令+参数 #First Dockerfile 注释 FROM u ...
- SP11469 SUBSET-Balanced Cow Subsets meet-in-the-middle+状压
正解:折半搜索 解题报告: 传送门! 这题我开始看到的时候贼开心地就把这题的代码直接粘过来辣 然后就T辣,,,仔细思考一下,为什么呢? 因为会枚举到很多相同的状态 举个eg 20 1 1 1 1 1 ...
- CF576C Points on Plane 构造
正解:构造 解题报告: 先放下传送门趴QAQ 话说我jio得这题好玄学啊,,,就是,我实在觉得我这题做得完美无缺了?可就是过不去,,,而且它告诉我的奇异错误是"wrong output fo ...
- C++三大特性之多态
原文地址:https://qunxinghu.github.io/2016/09/08/C++%20%E4%B8%89%E5%A4%A7%E7%89%B9%E6%80%A7%E4%B9%8B%E5%A ...
- Linux替换字符串
sed命令批量替换多个文件中的字符串: 命令:sed -i “s/原字符串/新字符串/g” `grep 原字符串 -rl 所在目录` 例如:我要把 xy 替换为 mn,执行命令: sed -i “s/ ...
- 【Pyton】【小甲鱼】爬虫
一.什么是爬虫? 可以理解为一只蜘蛛,在不同的网页上爬来爬去,获取我们需要的资源 二.Python如何访问互联网 urllib(一个包)=url(网页地址)+lib() 第一部分:protocol:/ ...
- sql server 以10分钟分组 统计人数
请问针对时间段从每天早上7点开始统计每十分钟人 解决思路: 我以前做过一个关于月份的,是说每3个月以分组,其实是一样的.不过可能啊,整体数据量大会有问题.如果你只是求一天的,那绝对没问题.[1]如果只 ...
- 【深入理解javascript】执行上下文
参考原文:执行上下文 1.每一个执行上下文,工作分为三个阶段: 准备阶段–>执行阶段–>调用阶段 准备阶段:代码执行之前,设置数据,相当于初始化. 执行阶段:开始执行每一行代码. 调用阶段 ...