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-实现并发处理的更多相关文章

  1. 网络编程socket

    socket socket解释 socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄. 应用程序通常通过"套接字"向网络发出请求或者应答 ...

  2. Python开发【第八篇】:socket网络编程

    服务端: import socket server = socket.socket() #绑定要监听的端口 server.bind(('localhost',6969)) #监听 server.lis ...

  3. python笔记-10(socket提升、paramiko、线程、进程、协程、同步IO、异步IO)

    一.socket提升 1.熟悉socket.socket()中的省略部分 socket.socket(AF.INET,socket.SOCK_STREAM) 2.send与recv发送大文件时对于黏包 ...

  4. Python异步非阻塞IO多路复用Select/Poll/Epoll使用,线程,进程,协程

    1.使用select模拟socketserver伪并发处理客户端请求,代码如下: import socket import select sk = socket.socket() sk.bind((' ...

  5. socket实现简单的FTP

    一.开发环境 server端:centos 7  python-3.6.2 客户端:Windows 7 python-3.6.2 pycharm-2018 程序目的:1.学习使用socketserve ...

  6. 图解Python网络编程

    返回目录 本篇索引 (1)基本原理 (2)socket模块 (3)select模块 (4)asyncore模块 (5)asynchat模块 (6)socketserver模块 (1)基本原理 本篇指的 ...

  7. 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) ...

  8. socketServer并发处理socket

    socketserver简单介绍 ''' socketserver:是对socket的封装,实现并发处理 前两个TCP,UDP常用,后两个不常用 ''' import socketserver soc ...

  9. Python(七)Socket编程、IO多路复用、SocketServer

    本章内容: Socket IO多路复用(select) SocketServer 模块(ThreadingTCPServer源码剖析) Socket socket通常也称作"套接字" ...

  10. socketserver 分块记录

    网络编程 Socket(TCP,IP)套接字 服务端 运行起来, 客户端 客户端 客户端 客户端 服务端: import socket sk = socket.socket() #绑定端口号 sk.b ...

随机推荐

  1. 从细节处谈Android冷启动优化

    本文来自网易云社区 Android APP冷启动优化,对于Android开发同学而言可能是个老生常谈的技优了. 之所以花时间写一篇冷启动优化的文章: 我想从另外一个角度来说冷启动优化,如题所述,从细节 ...

  2. 100万套PPT模板,包含全宇宙所有主题类型PPT,绕宇宙100圈,持续更新

    100万套PPT模板,包含全宇宙所有主题类型PPT(全部免费,都是精品,没有一张垃圾不好看的PPT,任何一张PPT拿来套入自己的信息就可以立马使用),绕宇宙100圈,任意一个模板在某文库上都价不菲.强 ...

  3. MySQL日期函数、时间函数总结(MySQL 5.X)

    一.获得当前日期时间函数 1.1 获得当前日期+时间(date + time)函数:now() select now(); # :: 除了 now() 函数能获得当前的日期时间外,MySQL 中还有下 ...

  4. C++ 基础面试题-2

    请写出一下程序的输出内容 /* ** 2018/03/21 22:02:03 ** Brief: ** Author:ZhangJianWei ** Email:Dream_Dog@163.com * ...

  5. Linux命令应用大词典-第31章 设备管理

    31.1 udevadm info:查询udev数据库中的设备信息 31.2 mkdnod:创建块设备和字符设备文件 31.3 MAKEDEV:创建/dev中的设备 31.4 lsblk:列出块设备信 ...

  6. 5.hadoop常用命令

    1. 单独启动和关闭hadoop服务 启动名称节点 #hadoop-daemon.sh start namenode 启动数据节点 #hadoop-daemons.sh start datanode ...

  7. URAL 1519 Formula 1(插头DP,入门题)

    Description Background Regardless of the fact, that Vologda could not get rights to hold the Winter ...

  8. Median Weight Bead(最短路—floyed传递闭包)

    Description There are N beads which of the same shape and size, but with different weights. N is an ...

  9. ACM 第六天

    图论 网络流 最大流 INF(初始值) 路径上权值最小的边,决定流量大小. 流量网络的三个特性: ①流量控制 ②反对称性 ③流量守恒 残余网络:保留了c(e)容量<f(e)流量[可以继续流,因为 ...

  10. Uncaught ReferenceError: wx is not defined

    程序的分享功能调用了微信的接口,但是忽然发现就报这个错误, Uncaught ReferenceError: wx is not defined 同时下方还有这个错误 This content sho ...