1. 程式人生 > >Python網絡編程之socket模塊

Python網絡編程之socket模塊

體系 font 代碼 break 操作系統 傳輸數據 recv 包括 ext

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模塊