Python SocketServer使用介绍

1、简介:

SocketServer是python的一个网络服务器框架,可以减少开发人员编写网络服务器程序的工作量。

SocketServer总共有4个server基类。

TCPServer:负责处理TCP协议。

UDPServer:负责处理UDP协议。

UnixStreamServer:只适用于类unix平台,不常用。

UnixDatagramServer:只适用于类unix平台,不常用。

这4个类会同步处理每一个request,也就是说只有当前的request处理完才会处理下一个request,这种方式显然很不合理,如果当前的request处理过慢的话就会导致“堵塞”。正确的处理方式应该是开辟新的进程或线程去处理不同的request,通过混合继承ForkingMixIn或ThreadingMixIn类即可解决此问题。

2、创建SocketServer

使用SocketServer创建一个网络服务程序只需要几个简单的步骤:

(1)、创建处理request的类,创建方法为:继承BaseRequestHandler类,并重载handle()方法。该方法将被回调用做处理当前接收到的request。

注意:一般的做法是直接继承StreamRequestHandler或者DatagramRequestHandler。比如:

class MyTCPHandler(SocketServer.StreamRequestHandler):

(2)、实例化一个server基类(比如TCPServer)的对象,并发服务器地址和处理request的类作为参数传入。

(3)、使用server基类对象调用handle_request()或serve_forever()方法,即可处理一个或多个request。

(4)、如果需要创建多进程或多线程的服务器程序,则可以通过混合继承ForkingMixIn或ThreadingMixIn类来实现,比如:

class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass //创建一个多线程的TCP服务器。

注意:ThreadingMixIn必须要放在TCPServer前面。

3、server类方法说明:

(1)、class SocketServer.BaseServer

这是所有类的超类,只定义接口,大部分均在子类中实现。

(2)、BaseServer.handle_request()

该方法用于处理单一的request。按顺序调用get_request(), verify_request()和   process_request().

(3)、BaseServer.serve_forever(poll_interval=0.5)

循环轮询处理request

(4)、BaseServer.address_family

协议簇信息,比如socket.AF_INET and socket.AF_UNIX

(5)、BaseServer.RequestHandlerClass

开发者自定义的用于处理request的类,每个request都会对应实例化一个request handle       类进行处理。

(6)、BaseServer.server_address

服务器要监听的地址和端口的二元组,比如(0.0.0.0,8080)

(7)、BaseServer.finish_request()

实例化开发者自定义request handle类,然后调用handle()方法处理当前的request。

(8)、

4、request handler类方法说明:

由用户自定义并传入SocketServer,由server类实例化来处理当前的request。需要注意的是:Request handler类必须要复写handle()方法,其它方法也可以复写,但不做强制。

(1)、RequestHandler.handle()

开发者必须在此方法里面实现对当前request的所有处理,在该方法里面有几个实例化的属性可以直接使用:self.request代表当前的request对象,self.client_address代表客户端地址,self.server代表服务器对象。对于TCP链接,self.request是当前request的socket。self.rfile和self.wfile可分别用于读取客户端数据和向客户端返回数据。

5、样例代码:

5.1、创建TCP类型的SocketServer:

import SocketServer
class MyTCPHandler(SocketServer.BaseRequestHandler): #定义request handler类,从BaseRequestHandler类继承 def handle(self): #复写handle()方法,注意:该方法必须复写,用于处理当前的request
self.data = self.request.recv(1024).strip() #self.request是和客户端连接的套接字,可直接使用
print "{} wrote:".format(self.client_address[0])
print self.data
self.request.sendall(self.data.upper()) class MyTCPHandler(SocketServer.StreamRequestHandler): #定义request handler类,从StreamRequestHandler类继承 def handle(self):
self.data = self.rfile.readline().strip() #self.rfile/self.wfile是文件格式类型的socket,相当于对原始socket的封装,让读写网络数据向读写文件一样容易
print "{} wrote:".format(self.client_address[0])
print self.data
self.wfile.write(self.data.upper()) if __name__ == "__main__":
HOST, PORT = "localhost", 9999
server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler) #传入监听地址、端口号和request handler类
server.serve_forever() #启动监听处理request

5.2、创建UDP类型的SocketServer:

import SocketServer

class MyUDPHandler(SocketServer.BaseRequestHandler):
def handle(self):
data = self.request[0].strip()
socket = self.request[1]
print "{} wrote:".format(self.client_address[0])
print data
socket.sendto(data.upper(), self.client_address)
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
server = SocketServer.UDPServer((HOST, PORT), MyUDPHandler)
server.serve_forever()

5.3、创建多线程类型的TCP SocketServer:

import socket
import threading
import SocketServer
class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler):
def handle(self):
data = self.request.recv(1024)
cur_thread = threading.current_thread()
response = "{}: {}".format(cur_thread.name, data)
self.request.sendall(response) class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):#继承ThreadingMixIn表示使用多线程处理request,注意这两个类的继承顺序不能变
pass def client(ip, port, message):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((ip, port))
try:
sock.sendall(message)
response = sock.recv(1024)
print "Received: {}".format(response)
finally:
sock.close() if __name__ == "__main__":
HOST, PORT = "localhost", 0
server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
ip, port = server.server_address
server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = True
server_thread.start()
print "Server loop running in thread:", server_thread.name
client(ip, port, "Hello World 1")
client(ip, port, "Hello World 2")
client(ip, port, "Hello World 3")
server.shutdown()

执行结果:

使用Python SocketServer快速实现多线程网络服务器的更多相关文章

  1. Django是Python下的一款网络服务器框架

    被解放的姜戈01 初试天涯   Django是Python下的一款网络服务器框架.Python下有许多款不同的框架.Django是重量级选手中最有代表性的一位.许多成功的网站和APP都基于Django ...

  2. python 网页爬虫+保存图片+多线程+网络代理

    今天,又算是浪费了一天了.python爬虫,之前写过简单的版本,那个时候还不懂原理,现在算是收尾吧. 以前对网页爬虫不了解,感觉非常神奇,但是解开这面面纱,似乎里面的原理并不是很难掌握.首先,明白一个 ...

  3. Python网络编程(3)——SocketServer模块与简单并发服务器

    主要类型 该模块有四个比较主要的类,其中常用的是 TCPServer 和 UDPServer. 1. TCPServer 2. UDPServer 3. UnixStreamServer,类似于TCP ...

  4. 【Python】使用socketserver建立一个异步TCP服务器

    概述 这篇文章是讲解如何使用socketserver建立一个异步TCP服务器,其中Python版本为3.5.1. socketserver主要的类 socketserver模块中的类主要有以下几个:1 ...

  5. Python全栈【Socket网络编程】

    Python全栈[socket网络编程] 本章内容: Socket 基于TCP的套接字 基于UDP的套接字 TCP粘包 SocketServer 模块(ThreadingTCPServer源码剖析) ...

  6. Python标准库08 多线程与同步 (threading包)

    Python主要通过标准库中的threading包来实现多线程.在当今网络时代,每个服务器都会接收到大量的请求.服务器可以利用多线程的方式来处理这些请求,以提高对网络端口的读写效率.Python是一种 ...

  7. crawler4j:轻量级多线程网络爬虫

    crawler4j是Java实现的开源网络爬虫.提供了简单易用的接口,可以在几分钟内创建一个多线程网络爬虫. 安装 使用Maven 使用最新版本的crawler4j,在pom.xml中添加如下片段: ...

  8. 自己动手实现网络服务器(Web Server)——基于C#

    前言 最近在学习网络原理,突然萌发出自己实现一个网络服务器的想法,并且由于第三代小白机器人的开发需要,我把之前使用python.PHP写的那部分代码都迁移到了C#(别问我为什么这么喜欢C#),之前使用 ...

  9. python socket 实现的简单http服务器

    预备知识: 关于http 协议的基础请参考这里. 关于socket 基础函数请参考这里. 关于python 网络编程基础请参考这里. 一.python socket 实现的简单http服务器   废话 ...

随机推荐

  1. C++之指针,引用与数组

    引用只是对象的另一个名字,通过在变量名前面添加"&”符号来定义,而指针保存的是另一个对象的地址,它们两都提供了间接访问所服务变量的途径. 但是它们的差别还是挺大的: 先从它们的值说起 ...

  2. python中的enumerate获取迭代元素的下标

    以前迭代的时候,需要获取次数都是如下格式: index=1 for node in nodes: if index==3: continue print(node.text_content())ind ...

  3. 计数排序的实现--适用于元素均较小的seq

    今天无聊就打算把所有的排序算法都看一遍... 计数排序的时间复杂度是O(n),在算法导论中,用决策树模型中论证了,比较排序的情况为nlogn的复杂度.而计数排序的时间复杂度小于他的原因就是它不需要进行 ...

  4. 【codeforces85D】

    去实验培训回来了……写个题先玩玩 这题给人一种平衡树的感觉 但是呢,实际上操作离线+离散化+线段树一样能做 #include<bits/stdc++.h> #define lson (o& ...

  5. 多路复用I/O模型epoll() 模型 代码实现

    epoll模型 int epoll_create(int maxevent) //创建一个epoll的句柄 然后maxevent表示监听的数目的大小int epoll_ctl(int epollfd, ...

  6. POJ-2778

    DNA Sequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12726   Accepted: 4862 Des ...

  7. 一个有趣的基于Django的调试插件--django-debug-toolbar

    django-debug-toolbar 介绍 django-debug-toolbar 是一组可配置的面板,可显示有关当前请求/响应的各种调试信息,并在单击时显示有关面板内容的更多详细信息. git ...

  8. hdu 3729(二分图最大匹配)

    I'm Telling the Truth Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  9. react初体验

    function Guest() { return ( <h1>pls login in</h1> ); } function User() { return ( <h1 ...

  10. [转载] 更改pip源至国内镜像,显著提升下载速度

    原文地址: https://blog.csdn.net/lambert310/article/details/52412059 经常在使用python的时候需要安装各种模块,而pip是很强大的模块安装 ...