Python網絡編程之socket模塊
1.網絡協議
網絡協議是網絡中進行數據交換與傳輸所需的規則、標準或約定,得到實用主要由語法(數據與信息的結構形式)、語義和同步(事件的實現順序)三個要素組成。
世界上最先提出的協議理論模型是由國際標準組織(ISO)提出的開放系統互聯基本參考模型(OSI),它采用的是七層協議的體系結構。雖然OSI清晰完整,但終因復雜又不實用而沒有得到實用。另一方面,使用了簡化的OSI的TCP/IP協議卻得到了非常廣泛的應用,它是一個四層的體系結構,包括應用層、運(傳)輸層、網際(絡)層和網絡接口層。
應用層 (FTP、SMTP、HTTP等) |
傳輸層 (TCP、UDP) |
網絡層 (IP) |
網絡接口層
|
TCP/IP協議圖
TCP/IP協議其實是一個協議簇,不僅包括TCP和IP協議,還包括UDP、FTP、HTTP、SMTP等,此外還包括一些圖中沒顯示的ICMP、ARP、RARP等協議。
這種分成的協議結構還表示出,上層協議需要傳輸的數據,應該交給它緊鄰的下層。而應用層和傳輸分別有兩個以上的協議,所以對於應用層來說,不同的協議數據可以通過傳輸層的不同協議來傳輸。
2、socket 模塊
TCP/IP 協議中的 TCP 和 UDP 協議都通一種名為套接字(socket)來實現網絡功能。套接字是一種類文件對象,它使程序能夠接受客戶端的連接或建立對客戶端的連接,用以發送和接收數據。無論是客戶端程序還是服務器端程序,為了進行網絡通信,都要創建套接字對象。
在 Python 標準庫中,使用 socket 模塊中提供的 socket 對象,可以在計算機網絡中建立服務器與客戶端,並且能夠進行通信。服務器端需要建立一個 socket 對象,並等待客戶端的連接。客戶端使用 socket 對象與服務器端進行連接,一旦連接成功,客戶端和服務端就可以進行通信了。
socket 模塊中的 socket 對象是 socket 網絡編程的基礎對象,其初始化原型
socket(family,type,proto)
其參數含義:
family:地址族,可選參數。默認AF_INET(IPv4),也可以是AF_INET6 或者是 AF_UNIX;
type:socket 類型,可選參數。默認SOCK_STREAM(TCP協議),可用SOCKET_DGRAM(UDP協議);
proto:協議類型,可選參數。默認為0。
作為服務器端的 socket 對象主要應用以下常用方法:
1.bind(address)
其參數 address 是由IP地址和端口組成的元組,如‘(‘127.0.0.1‘, 1051)’ 。如果IP地址為空,則表示本機。它的作用是使用socket和服務器地址相關聯。
2.listen(backlog)
參數backlog指定在拒接連接之前,操作系統允許它的最大掛起連接數量。最小值為0(如果用戶使用了更小的值,則會自動被置為0),大部分程序最多設置為5就足夠了。
該方法將socket設置為服務器模式,之後就可以電泳一下的accept()方法等待客戶端的連接。
3.accept()
它會等待進入的連接,並返回一個由新建的與客戶端的socket連接和客戶端地址組成的元組,而客戶的地址也是一個由客戶端IP地址和端口組成的元組。
4.close()
這個方法的作用就是關閉該socket。停止本程序與服務器或客戶端的連接。
5.recv(buffersize[,flag])
用於接受遠程連接發來的信息,並返回該信息,其類型為bytes。buffersize可以設定緩沖區的大小。
6.send(data[,flags])
用於向連接的遠端發送信息,data應該是bytes類型的數據。其返回值為一已傳送的字節數。其傳輸的數據長度有一定的限度。
7.sendall(data[,flags])
這個方法與send()方法相似,但是有時候在傳輸數據時,由於數據過多,用send()方法無法一次性傳輸,用sendall()方法可以解決這一問題,而sendall()也是通過循環運行send()方法來進行傳輸。
而建立服務器端的socket就要依次使用這幾個方法,其基本順序為:
3.創建一個服務器端
1 #!/usr/bin/python 2 # -*- coding: UTF-8 -*- 3 import socket 4 5 sk = socket.socket() #創建socket對象 6 address = (‘127.0.0.1‘, 8001) 7 sk.bind(address) #綁定本機地址 8 sk.listen(5) #監聽 9 print(‘waiting...‘) 10 conn,addr = sk.accept() #等待客戶端連接 11 12 while True: 13 #防止客戶端異常關閉,導致服務器端程序出錯 14 try: 15 data = conn.recv(1024) 16 except Exception: 17 data = None 18 #當客戶端傳送的數據為空時,關閉服務器端與客戶端之間的連接,等待其他客戶端連接 19 if not data: 20 conn.close() 21 conn,addr = sk.accept() 22 continue 23 print(str(data, ‘utf8‘)) # 因為接收的數據類型為bytes,所以轉換成字符串再打印 24 inp = input(‘>>>‘) 25 conn.send(bytes(inp, ‘utf8‘)) #傳送的數據類型應為bytes 26 27 sk.close()
4.創建一個客戶端
相比用socket建立服務器端而言,建立客戶端程序簡單多了。當然還是需要創建一個socket的實例,而後調這個socket實例的connect()方法來連接服務器端即可。這個方法原型為:
connect(address)
參數address 通常也是一個元組(由一個主機名/IP地址,端口構成),當然要連接本地計算機的話,主機可直接使用‘localhost‘,它用於將socket連接到遠程以address為地址的計算機。
用socket 建立客戶端的基本流程:
代碼實現:
1 #!/usr/bin/python 2 # -*- coding: UTF-8 -*- 3 import socket 4 5 sk = socket.socket() #創建套接字 6 address = (‘127.0.0.1‘, 8001) 7 sk.connect(address) # 與服務器端連接 8 while True: 9 inp = input(‘>>>‘) 10 if inp == ‘exit‘: 11 break 12 sk.send(bytes(inp, ‘utf8‘)) 13 data = sk.recv(1024) 14 print(str(data, ‘utf8‘)) 15 16 sk.close()
Python網絡編程之socket模塊