SocketServer-实现并发处理
Python提供了两个基本的socket模块。
一个是socket,它提供了标准的BSD Socket API;另一个是socketServer,它提供了服务器中心类,可以简化网络服务器的开发,其实就是对socket()的再封装。
1.前言:
虽说用Python编写简单的网络程序很方便,但复杂一点的网络程序还是用现成的框架比较好。这样就可以专心事务逻辑,而不是套接字的各种细节。SocketServer模块简化了编写网络服务程序的任务。同时SocketServer模块也是Python标准库中很多服务器框架的基础。
2.网络服务类:
SocketServer提供了4个基本的服务类:
TCPServer针对TCP套接字流
UDPServer针对UDP数据报套接字
UnixStreamServer和UnixDatagramServer针对UNIX域套接字,不常用。
3.请求处理类:
要实现一项服务,还必须派生一个handler class请求处理类,并重写父类的handle()方法。handle方法就是用来专门是处理请求的。该模块是通过服务类和请求处理类组合来处理请求的。
SocketServer模块提供的请求处理类有BaseRequestHandler,以及它的派生类StreamRequestHandler和DatagramRequestHandler。从名字看出可以一个处理流式套接字,一个处理数据报套接字。
4.总结用SocketServer创建一个服务的步骤:
1). 创建一个request handler class(请求处理类),并且这个类要继承BaseRequestHandler class,而且还要重写父类里面的handle()方法,跟客户端所有的交互都是在handle()里面完成的。
2). 实例化一个server class对象(TCPServer,UDPServer,UnixStreamServer,UnixDatagramServer 四选一),并将服务的地址和之前创建的request handler class(请求处理类)传递给实例化后的server class对象。
3). 调用server class对象的handle_request() (只处理一个请求)或 serve_forever()(处理多个请求)方法来开始处理请求。
5.
----socketserver
虽说用Python编写简单的网络程序很方便,但复杂一点的网络程序还是用现成的框架比较 好。这样就可以专心事务逻辑,而不是套接字的各种细节。SocketServer模块简化了编写网络服务程序的任务。同时SocketServer模块也 是Python标准库中很多服务器框架的基础。
socketserver在python2中为SocketServer,在python3种取消了首字母大写,改名为socketserver。
socketserver中包含了两种类,一种为服务类(server class),一种为请求处理类(request handle class)。前者提供了许多方法:像绑定,监听,运行…… (也就是建立连接的过程) 后者则专注于如何处理用户所发送的数据(也就是事务逻辑)。
一般情况下,所有的服务,都是先建立连接,也就是建立一个服务类的实例,然后开始处理用户请求,也就是建立一个请求处理类的实例。
一个基于SocketServer的服务器示例: from SocketServer import TCPServer,StreamRequestHandler #定义请求处理类 class Handler(StreamRequestHandler): def handle(self): addr = self.request.getpeername() print 'Got connection from ',addr self.wfile.write('Thank you for connecting') server = TCPServer(('',1234), handler)#实例化服务类对象 server.server_forever()#开启服务
5.实现异步,支持多连接
前面介绍服务类时提到过,四个基本的服务类默认是同步模型的。要想支持异步可以利用多继承从ForkingMixIn 或ThreadingMixInmix-in classes和一个基本的服务类继承来定义一个支持异步的服务类。比如:
class Server(ThreadingMixIn, TCPServer): pass
ForkingMixIn 要考虑进程间的通信。ThreadingMixIn要考虑线程访问同一变量时的同步和互斥。
一个使用了多线程处理的服务器示例:
from SocketServer import TCPServer, ThreadingMixIn, StreamRequestHandler
#定义支持多线程的服务类,注意是多继承
class Server(ThreadingMixIn, TCPServer): pass
#定义请求处理类
class Handler(StreamRequestHandler):
def handle(self):
addr = self.request.getpeername()
print 'Got connection from ',addr
self.wfile.write('Thank you for connection')
server = Server(('', 1234), Handler)#实例化服务类
server.serve_forever()#开启服务
SocketServer内部使用 IO多路复用 以及 “多线程” 和 “多进程” ,从而实现并发处理多个客户端请求的Socket服务端。即:每个客户端请求连接到服务器时,Socket服务端都会在服务器是创建一个“线程”或者“进 程” 专门负责处理当前客户端的所有请求。
注:导入模块的时候 3.x版本是socketserver 2.x版本是SocketServer
启动服务端程序
- 执行 TCPServer.init 方法,创建服务端Socket对象并绑定 IP 和 端口
- 执行 BaseServer.init 方法,将自定义的继承自SocketServer.BaseRequestHandler 的类 - MyRequestHandle赋值给 self.RequestHandlerClass
- 执行 BaseServer.server_forever 方法,While 循环一直监听是否有客户端请求到达 ... 当客户端连接到达服务器
- 执行 ThreadingMixIn.process_request 方法,创建一个 “线程” 用来处理请求
- 执行 ThreadingMixIn.process_request_thread 方法
- 执行 BaseServer.finish_request 方法,执行 self.RequestHandlerClass() 即:执行 自定义 MyRequestHandler 的构造方法(自动调用基类BaseRequestHandler的构造方法,在该构造方法中又会调用 MyRequestHandler的handle方法)
1. SocketServer基础-服务器端:
import socketserver class MyTCPHandler(socketserver.BaseRequestHandler): #自己写的请求处理类,每个客户端的请求过来,都会实例它。MyTCPHandler def handle(self): #重写handle()
while True:
self.data = self.request.recv(1024).strip()
print("{} wrote:".format(self.client_address[0])) #打印客户端的IP地址
print(self.data)
if not self.data: #客户端断开了
print(self.client_address,'has disconnected')
break
self.request.sendall(self.data.upper()) #变成大写,传回给客户端。 if __name__ == "__main__":
HOST, PORT = "localhost", 9999
server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
SocketServer基础-客户端:
import socket
client=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)
print("recv:",data.decode())
client.close()
客户端运行结果:
>>:ls
recv: LS
>>:df
recv: DF
>>:cmd
recv: CMD
>>:abc
recv: ABC
>>:
2. SocketServer基础-服务器端:当客户端断开的时候抓住异常
import socketserver class MyTCPHandler(socketserver.BaseRequestHandler): #自己写的请求处理类,每个客户端的请求过来,都会实例它。MyTCPHandler def handle(self): #重写handle()
while True:
try:
self.data = self.request.recv(1024).strip()
print("{} wrote:".format(self.client_address[0])) #打印客户端的IP地址
print(self.data) self.request.sendall(self.data.upper()) #变成大写,传回给客户端。
except ConnectionResetError as e:
print('Error is: ',e) #客户端断开时抛出的异常
break if __name__ == "__main__":
HOST, PORT = "localhost", 9999
server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
SocketServer基础-客户端:当客户端断开的时候抓住异常
import socket
client=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)
print("recv:",data.decode())
client.close()
客户端运行结果:
>>:ls
recv: LS
>>:df
recv: DF
>>:abc
recv: ABC
>>:
Process finished with exit code 1
服务器端运行结果:
127.0.0.1 wrote:
b'ls'
127.0.0.1 wrote:
b'df'
127.0.0.1 wrote:
b'abc'
error is: [WinError 10054] An existing connection was forcibly closed by the remote host
3. 实现多并发-服务器端:
import socketserver class MyTCPHandler(socketserver.BaseRequestHandler): #自己写的请求处理类,每个客户端的请求过来,都会实例它。MyTCPHandler def handle(self): #重写handle()
while True:
try:
self.data = self.request.recv(1024).strip()
print("{} wrote:".format(self.client_address[0])) #打印客户端的IP地址
print(self.data) self.request.sendall(self.data.upper()) #变成大写,传回给客户端。
except ConnectionResetError as e:
print('Error is: ',e) #客户端断开时抛出的异常
break if __name__ == "__main__":
HOST, PORT = "localhost", 9999
server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
实现多并发-客户端:
import socket
client=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)
print("recv:",data.decode())
client.close()
多个客户端同时连服务器,互相没有影响
|
SocketServer-实现并发处理的更多相关文章
- 网络编程socket
socket socket解释 socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄. 应用程序通常通过"套接字"向网络发出请求或者应答 ...
- Python开发【第八篇】:socket网络编程
服务端: import socket server = socket.socket() #绑定要监听的端口 server.bind(('localhost',6969)) #监听 server.lis ...
- python笔记-10(socket提升、paramiko、线程、进程、协程、同步IO、异步IO)
一.socket提升 1.熟悉socket.socket()中的省略部分 socket.socket(AF.INET,socket.SOCK_STREAM) 2.send与recv发送大文件时对于黏包 ...
- Python异步非阻塞IO多路复用Select/Poll/Epoll使用,线程,进程,协程
1.使用select模拟socketserver伪并发处理客户端请求,代码如下: import socket import select sk = socket.socket() sk.bind((' ...
- socket实现简单的FTP
一.开发环境 server端:centos 7 python-3.6.2 客户端:Windows 7 python-3.6.2 pycharm-2018 程序目的:1.学习使用socketserve ...
- 图解Python网络编程
返回目录 本篇索引 (1)基本原理 (2)socket模块 (3)select模块 (4)asyncore模块 (5)asynchat模块 (6)socketserver模块 (1)基本原理 本篇指的 ...
- python_way day10 python和其他语言的作用域 、 python2.7多继承和3.5多继承的区别 、 socket 和 socketserver源码(支持并发处理socket,多进程,多线程)
python_way day10 1.python的作用域和其他语言的作用域 2.python2.7多继承和3.5多继承的区别 3.socket和socketserver源码(并发处理socket) ...
- socketServer并发处理socket
socketserver简单介绍 ''' socketserver:是对socket的封装,实现并发处理 前两个TCP,UDP常用,后两个不常用 ''' import socketserver soc ...
- Python(七)Socket编程、IO多路复用、SocketServer
本章内容: Socket IO多路复用(select) SocketServer 模块(ThreadingTCPServer源码剖析) Socket socket通常也称作"套接字" ...
- socketserver 分块记录
网络编程 Socket(TCP,IP)套接字 服务端 运行起来, 客户端 客户端 客户端 客户端 服务端: import socket sk = socket.socket() #绑定端口号 sk.b ...
随机推荐
- create-react-app创建react项目 css模块化处理
用的css预处理器用sass,其他大同小异. 用create-react-app创建项目,执行npm run eject弹出配置文件(此操作不可逆): 配置sass,用的最新的CRA,webpack4 ...
- Java开发工程师(Web方向) - 01.Java Web开发入门 - 第4章.Maven
第4章--Maven Maven实战 Java Web应用的部署: 手动式: 编译:javac -cp $CATALINA_HOME/lib/servlet-api.jar web-inf/class ...
- 一段代码-Java
在打算写这么一篇文章的时候,想到很多,觉得要是全都写下来的话,估计BZ也不知道要写多少,总之,好多吧!那么,就让BZ一切从简... 我们知道java它的特殊性在于,用它所写代码的运行是依靠自己的一套j ...
- HDU-1496(哈希表)
Hash入门第一题 题意: 问题描述 考虑具有以下形式的方程: a * x1 ^ 2 + b * x2 ^ 2 + c * x3 ^ 2 + d * x4 ^ 2 = 0 a,b,c,d是来自区间[- ...
- 【转】网游服务器中的GUID(唯一标识码)实现-基于snowflake算法
本文中的算法采用twitter的snowflake算法,具体请搜索介绍,原来是用Scala写的,因我项目需要,改写成C++语言,主要用于高效的生成唯一的ID, 核心算法就是毫秒级时间(41位)+机器I ...
- vs_code 快捷键
一般的Ctrl+Shift+P,F1显示命令面板按Ctrl+P快速打开,到文件.Ctrl + Shift + N新窗口/实例Ctrl + Shift + W /关闭窗口实例Ctrl +.用户设置Ctr ...
- kafka stream 低级别的Processor API动态生成拓扑图
public class KafkaSream { public static void main(String[] args) { Map<String, Object> props = ...
- LeetCode - 463. Island Perimeter - O(MN)- (C++) - 解题报告
原题 原题链接 You are given a map in form of a two-dimensional integer grid where 1 represents land and 0 ...
- SPOJ 694 Distinct Substrings/SPOJ 705 New Distinct Substrings(后缀数组)
Given a string, we need to find the total number of its distinct substrings. Input T- number of test ...
- HDU 4115 Eliminate the Conflict(2-SAT)(2011 Asia ChengDu Regional Contest)
Problem Description Conflicts are everywhere in the world, from the young to the elderly, from famil ...