Python基礎:網絡編程socketserver高級篇

socketserverhtml

此模塊簡化了socket的編寫。python

    一、它有一個基類,定義瞭如何創建鏈接。BaseServer提供了服務類接口,BaseServer使用了select建立了多線程。BaseServer下面有四個類:TCPServer、UnixStreamServer、UDPserver、UnixDatagramServer。json

 

    二、它還提供了請求處理類:定義瞭如何處理用戶數據。定義了三個方法setup\handler\finish,的接口,使用時,從新寫對應方法。服務器

 

    三、使用Forktheard和多線程

BaseServer模塊結構:socket

捕獲.JPG

服務處理類方法:
做用
BaseServer
超類,提供了API,並利用select建立了多線程。不能直接調用它使用。
TCPServer
建立每一個進程的socket,傳輸TCP數據。同時,也是一個基類。
UDPServer
傳輸UDP數據。
UnixStreamServer
Unix下使用
UnixDatagramServer Unix下使用
ThreadingTCPServer socketserver多路複用版。UDPServer\UnixStreamServer\UnixDatagramServer的多路複用版前加Threading
服務處理類BaseServer的方法
做用

fileno()
ide

返回服務器監聽套接字的整數文件描述符。一般用來傳遞給select.select(), 以容許一個進程監視多個服務器。
handle_request()

處理單個請求。處理順序:get_request(), verify_request(), process_request()。函數

若是用戶提供handle()方法拋出異常,將調用服務器的handle_error()方法。測試

若是self.timeout內沒有請求收到, 將調用handle_timeout()並返回handle_request()。
spa

serve_forever(poll_interval=0.5) 處理請求,直到一個明確的shutdown()請求。每poll_interval秒輪詢一次shutdown。忽略self.timeout。若是你須要作週期性的任務,建議放置在其餘線程。
shutdown()
告訴serve_forever()中止。for python2.6。
address_family
地址簇。socket.AF_INET等
HandlerRequestClass
用戶提供的請求處理類,爲每個請求建立一個實例。
server_address
偵聽的服務器地址。
socketSocket
服務器上偵聽傳入的請求socket對象的服務器。


下面方法能夠被子類重載,它們對服務器對象的外部用戶沒有影響。
finish_request() 實際處理RequestHandlerClass發起的請求並調用其handle()方法。 經常使用。
get_request() 接受socket請求,並返回二元組包含要用於與客戶端通訊的新socket對象,以及客戶端的地址。
handle_error(request, client_address) 若是RequestHandlerClass的handle()方法拋出異常時調用。默認操做是打印traceback到標準輸出,並繼續處理其餘請求。
handle_timeout() 超時處理。默認對於forking服務器是收集退出的子進程狀態,threading服務器則什麼都不作
process_request(request, client_address)
調用finish_request()建立RequestHandlerClass的實例。若是須要,此功能能夠建立新的進程或線程來處理請求,ForkingMixIn和ThreadingMixIn類作到這點。經常使用。
server_activate() 經過服務器的構造函數來激活服務器。默認的行爲只是監聽服務器套接字。可重載。
server_bind() 經過服務器的構造函數中調用綁定socket到所需的地址。可重載。
verify_request(request, client_address) 返回一個布爾值,若是該值爲True ,則該請求將被處理,反之請求將被拒絕。此功能能夠重寫來實現對服務器的訪問控制。默認的實現始終返回True。client_address能夠限定客戶端,好比只處理指定ip區間的請求。 經常使用。


服務處理類的變量(屬性):
做用
allow_reuse_address
是否容許地址重用,默認是False,能夠在子類裏更改。
request_queue_size
請求隊列的大小。若是單個請求須要很長的時間來處理,服務器忙時請求被放置到隊列中,最多能夠放request_queue_size個。一旦隊列已滿,來自客戶端的請求將獲得 「Connection denied」錯誤。默認值一般爲5 ,但能夠被子類覆蓋。
socket_type
服務器使用的套接字類型,socket.SOCK_STREAM和socket.SOCK_DGRAM等。
timeout
超時時間。以秒爲單位,或 None表示沒有超時。若是handle_request()在timeout內沒有收到請求,將調用handle_timeout()。


 

請求處理類的方法:
做用
setup()
處理請求以前的方法,能夠初始化。
handle()
處理請求的方法,處理與Client交互內容。
finish()
handler()處理完成後運行的方法。用於釋放和清理。


 

#服務端:

import socketserver

class Mysite(socketserver.BaseRequestHandler):                # 必須繼承socketserver基類
    
    def handle(self):                                        # 重寫基類裏的handler()方法,在這個方法裏處理接收、發送請求
        while True:
            recv_data = self.request.recv(1024)
            data = json.loads(recv_data.decode())             # 爲何用json?,由於我喜歡。。這包裝數字、字符、列表等等數據類型通吃
            print(data)
            
            if data.lower() == "exit":                        # 檢測到exit退出
                print("客戶端退出!")
                break
                
            self.request.send(json.dumps(data.lower()).encode())    # 發送轉換小寫的數據給客戶端,而後進入到下一個循環
 
my_server = socketserver.TCPserver(("localhost", 9999), Mysite)     # 實例化socketserver,並傳送服務器ip、port和子類
my_server.serve_forever()
 
 
# 客戶端
import socket
 
class Myclient(object):
     def __init__(obj):                                    # 接收一個socket實例化的對象
         self.conn = obj
     
     def handle(self,ip,prot):                            # 定義一個數據交互的方法
     
         self.conn.connect((ip,port))                      # 綁定連接,其它把它放在init方法裏是否是會更好?
         
         while Ture:
         # 循環發送、接收數據
             cmd = input('輸入轉換的字符,exit退出!')
             
             if cmd.strip().lower() == 'exit':             # 若是輸入EXIT退出
                 print('退出!')
                 break
                 
             self.conn.send(json.dumps(cmd).encode())      # 發送輸入的數據
             
             recv_data = self.conn.recv(1024)              # 接收服務器轉換後的數據
             
             data = json.loads(recv_data.decode())         # json解碼
             
             print('轉換的:{}'.format(data))
 
my_socket = socket.socket()                                # 實例化socket對象
my_client = Myclient(my_socket)                            # 實例化自定義類,並傳入實例化的socket對象
my_client.handle("localhost",9999)                        # 調用數據交互方法


"""以上代碼博客裏手打,未經測試。 """

 

 

 

 

其它參考資料:

https://www.cnblogs.com/MnCu8261/p/5546823.html

http://www.javashuo.com/article/p-pzpkwkpi-mq.html

https://www.cnblogs.com/eric_yi/p/7701381.html

相關文章
相關標籤/搜索