SocketServer
模块是一个创建网络服务的框架。它由一系列的网络服务类和一系列的请求处理类组成。网络服务类处理通信相关事项,请求处理类处理协议相关事项。
要创建一个网络服务器,最基本的有三步:
- 继承
BaseRequestHandler
类,并重载handle()
方法。在handle()
方法中对客户端请求进行处理; - 实例化网络服务类,传入监听地址和服务处理类;网络服务类的
process_request
方法会调用该类的finish_request
方法,在finish_request
方法中完成对请求处理类的实例化; -
调用
serve_forever()
监听客户端请求。
#!/usr/bin/env python
#encoding:utf-8
import SocketServer
#1.继承请求处理类,并重载 handle 方法,在 handle() 方法中接收
#客户端的请求内容,并进行处理
class EchoRequestHandler(SocketServer.BaseRequestHandler):
def handle(self):
data = self.request.recv(1024)
self.request.send(data)
return
if __name__ == '__main__':
import socket
import threading
address = ('localhost', 0) #让操作系统决定监听的端口
#2.实例化网络服务类,传入监听地址和请求处理类
server = SocketServer.TCPServer(address, EchoRequestHandler)
ip, port = server.server_address # what port was assigned?
#3.新建一个线程,在线程中调用 server_forever() 方法,监听客户端请求
t = threading.Thread(target=server.serve_forever)
t.setDaemon(True) # don't hang on exit
t.start()
# 在主线程中实现一个客户端
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, port))
#发送数据
message = 'Hello, world'
print('Sending:{}'.format(message))
len_sent = s.send(message)
#接收数据
response = s.recv(len_sent)
print('Receive:{}'.format(response))
#关闭服务器,资源清理
server.shutdown()
s.close()
server.socket.close()
上面的例子存在一个问题,网络服务类与请求处理类在同一个线程中,也就是说,只有上一个请求处理完成后,才能接收并处理下一个请求。作为服务器这种同步的处理方式几乎不可以接受。
这时可以通过改造 TcpServer
类实现请求处理的线程化。
#!/usr/bin/env python
#encoding:utf-8
import SocketServer
#1.继承请求处理类,并重载 handle 方法,在 handle() 方法中接收
#客户端的请求内容,并进行处理
class EchoRequestHandler(SocketServer.BaseRequestHandler):
def handle(self):
data = self.request.recv(1024)
self.request.send(data)
return
#2.继承ThreadingMixIn和TCPServer类,实现请求处理的线程化
class ThreadedEchoServer(SocketServer.ThreadingMixIn,SocketServer.TCPServer):
pass
if __name__ == '__main__':
import socket
import threading
address = ('localhost', 0) #让操作系统决定监听的端口
#3.实例化网络服务类,传入监听地址和请求处理类
server = ThreadedEchoServer(address, EchoRequestHandler)
ip, port = server.server_address # what port was assigned?
#4.新建一个线程,在线程中调用 server_forever() 方法,监听客户端请求
t = threading.Thread(target=server.serve_forever)
t.setDaemon(True) # don't hang on exit
t.start()
# 在主线程中实现一个客户端
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, port))
#发送数据
message = 'Hello, world'
print('Sending:{}'.format(message))
len_sent = s.send(message)
#接收数据
response = s.recv(len_sent)
print('Receive:{}'.format(response))
#关闭服务器,资源清理
server.shutdown()
s.close()
server.socket.close()
在上面的例子中,ThreadingMixIn
类覆盖了 TcpServer
类的process_request
方法,并新建一个线程来处理该请求。
参考:
http://docs.python.org/3/library/socketserver.html
http://pymotw.com/2/SocketServer/index.html