在網易工作這半年來說,單純的寫了很多奇奇怪怪的腳本,比如說在沒有代碼權限的情況下如何得到QA測試的代碼覆蓋率?到頭來還是通過這個網絡編程來解決,之前沒有接觸過網絡編程,直接現學現賣完成任務。
網易有好處在吧,自己設計規劃一個系統,客戶端實現的功能,服務端實現的功能,還需要規劃每個功能點,畫時序圖,說實話這是原來在華爲根本接觸不到的,以前在華爲自己只是負責一個小功能的實現,基本上pm給出開發文檔,按部就班實現就好了,吃麪條,PM說你負責擀麪,就把面擀好了就行了,唯一的難度在於讀懂原來的代碼;在網易,一切從零開始,說白了就是要吃麪條,沒有面粉,也沒有小麥,只有一塊地和一把種子。
以上就是發牢騷,沒有貶低沒有褒獎。
------------------------------------------------------------------------------------------------------------------------------
作者首先就是引用下大佬的話,IPV4用完了,IPV6是出路。
本章內容:簡介;客戶端/服務器架構;套接字:通信端點; Python 中的網絡編程; *SocketServer 模塊; *Twisted 框架介紹;相關模塊。
2.1簡介
簡介。
2.2客戶端/服務端架構
簡要描述下CS架構,用戶作爲客戶端一次性請求永久運行的服務端。軟硬件都可以用。
2.2.1硬件客戶端/服務器架構
舉例子:打印機,文件服務器
2.2.2軟件客戶端/服務器架構
舉例子:web服務器,數據庫服務器,窗體服務器(這個有點抽象的)
2.2.3銀行出納員作爲服務器嗎
舉例說明cs架構:出納員作爲服務器“永久”在線服務隨時要來的客戶。
2.2.4客戶端/服務器網絡編程
服務器創建通信端點,等待客戶端連接並相應他們的請求,結束後通信終止。
2.3套接字:通信端點
套接字就是上面提到的通信端點。
2.3.1套接字
套接字可以比作電話線那個插孔;
AF:address family
現在用於進程間通訊(同一個計算機上),python用的AF_UNIX。
基於網絡的,現在用的AF_INET比較廣泛
總的來說,Python 只支持 AF_UNIX、 AF_NETLINK、 AF_TIPC 和AF_INET家族。
這章講的是網絡編程,所以使用AF_INET
2.3.3套接字地址:主機-端口對 重點
1.面向連接的套接字(TCP)
第一種TCP:是面向連接的,通訊之前必須建立一個連接。提供序列化的、可靠的和不重複的數據交付,沒有記錄邊界。每條信息都可以拆分成多個片段,並且每一條消息片段都確保能夠到達目的地,然後順序的拼接起來,最後將信息完整的傳遞給程序。
爲了創建TCP套接字,必須使用 SOCK_STREAM 作爲套接字類型。
因爲這些套接字(AF_INET)的網絡版本使用因特網協議( IP) 來搜尋網絡中的主機,所以整個系統通常結合這兩種協議( TCP 和 IP) 來進行。
TCP也可以用本地的套接字(非網絡,比如AF_LOCAL/ AF_UNIX),本地的就沒有使用IP地址。
2.無連接的套接字(UDP)
在通訊開始不需要建立連接,傳輸過程中無法確保它的順序性、可靠性和重複性,但是卻記錄了數據邊界,也就是說數據是整體發送的,並不是切分片段發送。
這玩意紙面數據這麼差誰用?但是它維護成本低,根本不用管,所以性能更好。
使用 SOCK_DGRAM 作爲套接字類型。
因爲這些套接字也使用因特網協議來尋找網絡中的主機,所以這個系統也有一個更加普通的名字,即這兩種協議( UDP 和IP)的組合名字,或 UDP/ IP。
2.4Python中的網絡編程
2.4.1socket() 模塊函數
創建套接字的一般語法是:socket( socket_family, socket_type, protocol = 0)
socket_family 是 AF_UNIX 或 AF_INET
socket_type是 SOCK_STREAM 或 SOCK_DGRAM
protocol通常省略,默認爲 0。
創建TCP/IP套接字:tcpSock = socket.socket( socket.AF_INET, socket.SOCK_STREAM)
創建UDP/IP套接字:udpSock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM)
2.4.2套接字對象(內置)方法
2.4.3 創建 TCP 服務器
創建 TCP 服務器僞代碼,目的是理解創建過程。
ss = socket() # 創建服務器套接字
ss.bind() # 套接字與地址綁定
ss.listen() # 監聽連接
inf_loop: # 服務器無限循環
cs = ss.accept() # 接受客戶端連接
comm_loop: # 通信循環
cs.recv()/ cs.send() # 對話(接收/發送)
cs.close() # 關閉客戶端套接字
ss.close() # 關閉服務器套接字#(可選)
socket.socket () 所有套接字都是通過使用 socket ()函數來創建的。
ss.listen()監聽開始之後,服務器開始無線循環中。
cs = ss.accept(),這個就是接受客戶端的函數,沒有連接的情況下,這個一般是阻塞的,就是說這個過程運行到這就卡住,指導有人連接後開始下一步。
cs.recv()/ cs.send()這個就是相互發送信息的函數
cs.close()關閉了連接
ss.close()服務端也關閉了。
上面這個是單服務端的例子,也就是服務端一次只能連接一個客戶端。
核心提示:多線程處理客戶端請求
書裏沒有寫,可以參考下我寫的這個例程:https://blog.csdn.net/marwenx/article/details/104760791
接下來是兩個例子,一個python2一個python3,直接將上面這些僞代碼實例化了,不在贅述。
2.4.4 創建 TCP 客戶端
僞代碼
cs = socket() # 創建客戶端套接字
cs.connect() # 嘗試連接服務器
comm_loop: # 通信循環
cs.send()/ cs.recv() # 對話(發送/接收)
cs.close() # 關閉客戶端套接字
所有套接字都是利用 socket.socket() 創建的。
利用套接字的 connect() 方法直接創建一個到服務器的連接。
cs.close() 關閉套接字,終止此次連接。
例子不在贅述。
2.4.5 執行 TCP 服務器和客戶端
這個就是動手實踐下就好,先運行服務端,再運行客戶端,第一次就很好玩。
核心提示:優雅地退出和調用服務器 close() 方法
這個書裏建議是用一個 try-except 語句中的 except 子句中,監控 EOFError 或KeyboardInterrupt異常,這樣你就可以在 except 或 finally 字句中關閉服務器的套接字。
我一般是發送一個特殊的字符串過去,比如說“exit”
2.4.6 創建 UDP 服務器