首頁  >  文章  >  後端開發  >  講解Python中SocketServer模組處理網路請求

講解Python中SocketServer模組處理網路請求

高洛峰
高洛峰原創
2017-03-01 14:17:581821瀏覽

SocketServer建立一個網路服務框架。它定義了類別來處理TCP,UDP, UNIX streams 和UNIX datagrams上的同步網路請求。

一、Server Types

有五個不同的伺服器類別在SocketServer中。

1.BaseServer定義了API, 而且他不是用來實例化和直接使用的。
2.TCPServer用作TCP/IP的socket通訊。
3.UDPServer使用datagram sockets。
4.UnixStreamServer和UnixDatagramServer使用Unix-domain sockets而且智慧在unix平台上使用。

二、Server Objects

建構一個伺服器, 透過它來監聽請求的位址和請求的處理類別(not instance)。

1.class SocketServer.BaseServer
這是模組中所有伺服器物件的超類,它定義了介面,實作大多數都在子類別中完成。

2.BaseServer.fileno

傳回一個整數檔案描述子來表示哪個伺服器正在監聽。這個函數最常見的傳遞給select.select(),允許監控多個相同處理過程的服務。

3.BaseServer.handle_request

處理單一的請求,這個函數會依序呼叫接下來的方法。 get_request(),verify_request和proccess_request。
使用者提供handle()方法拋出一個異常,那麼handle_error()方法會被呼叫。
self.timeout的時間內沒有收到請求,handle_timeout()和handle_request()將會回傳。

4.BaseServer.serve_forever

BaseServer.serve_forever(poll_interval=0.5),處理請求一直到明確的shutdown()請求。輪訓每隔poll_interval時間內關閉。忽略self.timeout,如果需要使用定時任務,需要使用其他執行緒。

5.BaseServer.shutdown

告訴serve_forever()迴圈停止。

6.BaseServer.RequestHandlerClass

使用者請求處理程序類,為每個請求建立這個類別的一個實例。

三、Implementing a Server

如果你建立一個伺服器,它通常可以重複使用現有的類別和簡單的提供一個自訂請求處理的類別。如果不符合需求,有幾種BaseServer方法覆寫一個子類別。

1.verify_request(reqeust, client_address): 必須傳回一個布林值,如果傳回True,請求將被處理,如果傳回False,請求將被拒絕。這個函數可以覆蓋來實現存取控制服務。
2.process_request(request, client_address): 呼叫finish_request來建立一個RequestHandlerClass()的實例,如果需要該函數可以建立一個新的程序或協程來處理請求。
3.finish_request(request, client_address): 建立一個請求處理實例。呼叫handle()來處理請求。

四、Request Handlers

請求處理程序做的大部分工作接收傳入的請求,並決定採取何種行動。處理程序負責實作「協定」上的套接字層(例如,HTTP或xml - rpc)。從傳入的請求處理程序讀取請求資料通道,流程,和寫一個回應。有三個方法可以重寫。

1.setup(): 準備請求的請求處理程序, 就是初始化運行在handle之前。
2.handle(): 做真正的請求工作。解析傳入的請求,處理資料和回傳回應。
3.finish(): 清理任意時間所建立的setup()。

五、範例

下面範例展示了tcp, udp與非同步

1.TCPServer 範例


#
import SocketServer


class MyHandler(SocketServer.BaseRequestHandler):
  
  def handle(self):
    self.data = self.request.recv(1024).strip()
    print '{} wrote:'.format(self.client_address[0])
    print self.data
    self.request.sendall(self.data.upper())


if __name__ == '__main__':
  HOST, PORT = 'localhost', 9999
  server = SocketServer.TCPServer((HOST, PORT), MyHandler)
  server.serve_forever()


2.UDPServr 範例


import SocketServer


class MyHandler(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), MyHandler)
  server.serve_forever()


#3.非同步範例

可以透過ThreadingMixIn和ForkingMixIn類別來建構非同步處理程序。


import socket
import threading
import SocketServer


class MyHandler(SocketServer.BaseRequestHandler):

  def handle(self):
    data = self.request.recv(1024)
    curr_thread = threading.current_thread()
    response = '{}: {}'.format(curr_thread.name, data)
    self.request.sendall(response)


class Server(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
  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 = Server((HOST, PORT), MyHandler)
  ip, port = server.server_address

  serer_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()
  server.server_close()


4.SocketServer 實作客戶端與伺服器間非阻塞通訊
(1)創建SocketServerTCP服務端


#创建SocketServerTCP服务器: 
import SocketServer 
from SocketServer import StreamRequestHandler as SRH 
from time import ctime 
 
host = 'xxx.xxx.xxx.xxx' 
port = 9999 
addr = (host,port) 
 
class Servers(SRH): 
  def handle(self): 
    print 'got connection from ',self.client_address 
    self.wfile.write('connection %s:%s at %s succeed!' % (host,port,ctime())) 
    while True: 
      data = self.request.recv(1024) 
      if not data:  
        break 
      print data 
      print "RECV from ", self.client_address[0] 
      self.request.send(data) 
print 'server is running....' 
server = SocketServer.ThreadingTCPServer(addr,Servers) 
server.serve_forever()


(2)建立SocketServerTCP用戶端


#
from socket import * 
 
host = 'xxx.xxx.xxx.xxx' 
port = 9999 
bufsize = 1024 
addr = (host,port) 
client = socket(AF_INET,SOCK_STREAM) 
client.connect(addr) 
while True: 
  data = raw_input() 
  if not data or data=='exit': 
    break 
  client.send('%s\r\n' % data) 
  data = client.recv(bufsize) 
  if not data: 
    break 
  print data.strip() 
client.close()


更講解Python中SocketServer模組處理網路請求相關文章請關注PHP中文網!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn