Python3 網路程式設計

Python3 網路程式設計

Python 提供了兩個級別訪問的網路服務。:

  • 低級別的網路服務支援基本的 Socket,它提供了標準的 BSD Sockets API,可以訪問底層作業系統Socket介面的全部方法。
  • 高級別的網路服務模組 SocketServer, 它提供了伺服器中心類,可以簡化網路伺服器的開發。

什麼是 Socket?

Socket又稱"套接字",應用程式通常通過"套接字"向網路發出請求或者應答網路請求,使主機間或者一臺計算機上的程序間可以通訊。


socket()函式

Python 中,我們用 socket() 函式來建立套接字,語法格式如下:

socket.socket([family[, type[, proto]]])

引數

  • family: 套接字家族可以是 AF_UNIX 或者 AF_INET
  • type: 套接字型別可以根據是面向連線的還是非連線分為SOCK_STREAMSOCK_DGRAM
  • protocol: 一般不填預設為0.

Socket 物件(內建)方法

函式 描述
伺服器端套接字
s.bind() 繫結地址(host,port)到套接字, 在AF_INET下,以元組(host,port)的形式表示地址。
s.listen() 開始TCP監聽。backlog指定在拒絕連線之前,作業系統可以掛起的最大連線數量。該值至少為1,大部分應用程式設為5就可以了。
s.accept() 被動接受TCP客戶端連線,(阻塞式)等待連線的到來
客戶端套接字
s.connect() 主動初始化TCP伺服器連線,。一般address的格式為元組(hostname,port),如果連接出錯,返回socket.error錯誤。
s.connect_ex() connect()函式的擴充套件版本,出錯時返回出錯碼,而不是丟擲異常
公共用途的套接字函式
s.recv() 接收TCP資料,資料以字串形式返回,bufsize指定要接收的最大資料量。flag提供有關訊息的其他資訊,通常可以忽略。
s.send() 傳送TCP資料,將string中的資料傳送到連線的套接字。返回值是要傳送的位元組數量,該數量可能小於string的位元組大小。
s.sendall() 完整發送TCP資料,完整發送TCP資料。將string中的資料傳送到連線的套接字,但在返回之前會嘗試傳送所有資料。成功返回None,失敗則丟擲異常。
s.recvfrom() 接收UDP資料,與recv()類似,但返回值是(data,address)。其中data是包含接收資料的字串,address是傳送資料的套接字地址。
s.sendto() 傳送UDP資料,將資料傳送到套接字,address是形式為(ipaddr,port)的元組,指定遠端地址。返回值是傳送的位元組數。
s.close() 關閉套接字
s.getpeername() 返回連線套接字的遠端地址。返回值通常是元組(ipaddr,port)。
s.getsockname() 返回套接字自己的地址。通常是一個元組(ipaddr,port)
s.setsockopt(level,optname,value) 設定給定套接字選項的值。
s.getsockopt(level,optname[.buflen]) 返回套接字選項的值。
s.settimeout(timeout) 設定套接字操作的超時期,timeout是一個浮點數,單位是秒。值為None表示沒有超時期。一般,超時期應該在剛建立套接字時設定,因為它們可能用於連線的操作(如connect())
s.gettimeout() 返回當前超時期的值,單位是秒,如果沒有設定超時期,則返回None。
s.fileno() 返回套接字的檔案描述符。
s.setblocking(flag) 如果 flag 為 False,則將套接字設為非阻塞模式,否則將套接字設為阻塞模式(預設值)。非阻塞模式下,如果呼叫 recv() 沒有發現任何資料,或 send() 呼叫無法立即傳送資料,那麼將引起 socket.error 異常。
s.makefile() 建立一個與該套接字相關連的檔案

簡單例項

服務端

我們使用 socket 模組的 socket 函式來建立一個 socket 物件。socket 物件可以通過呼叫其他函式來設定一個 socket 服務。

現在我們可以通過呼叫 bind(hostname, port) 函式來指定服務的 port(埠)

接著,我們呼叫 socket 物件的 accept 方法。該方法等待客戶端的連線,並返回 connection 物件,表示已連線到客戶端。

完整程式碼如下:

#!/usr/bin/python3
# 檔名:server.py

# 匯入 socket、sys 模組
import socket
import sys

# 建立 socket 物件
serversocket = socket.socket(
            socket.AF_INET, socket.SOCK_STREAM) 

# 獲取本地主機名
host = socket.gethostname()

port = 9999

# 繫結埠號
serversocket.bind((host, port))

# 設定最大連線數,超過後排隊
serversocket.listen(5)

while True:
    # 建立客戶端連線
    clientsocket,addr = serversocket.accept()      

    print("連線地址: %s" % str(addr))
    
    msg='歡迎訪問入門教學!'+ "\r\n"
    clientsocket.send(msg.encode('utf-8'))
    clientsocket.close()

客戶端

接下來我們寫一個簡單的客戶端例項連線到以上建立的服務。埠號為 9999。

socket.connect(hosname, port ) 方法開啟一個 TCP 連線到主機為 hostname 埠為 port 的服務商。連線後我們就可以從服務端獲取資料,記住,操作完成後需要關閉連線。

完整程式碼如下:

#!/usr/bin/python3
# 檔名:client.py

# 匯入 socket、sys 模組
import socket
import sys

# 建立 socket 物件
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 

# 獲取本地主機名
host = socket.gethostname() 

# 設定埠號
port = 9999

# 連線服務,指定主機和埠
s.connect((host, port))

# 接收小於 1024 位元組的資料
msg = s.recv(1024)

s.close()

print (msg.decode('utf-8'))

現在我們開啟兩個終端,第一個終端執行 server.py 檔案:

$ python3 server.py

第二個終端執行 client.py 檔案:

$ python3 client.py 
歡迎訪問入門教學!

這時我們再開啟第一個終端,就會看到有以下資訊輸出:

連線地址: ('192.168.0.118', 33397)

Python Internet 模組

以下列出了 Python 網路程式設計的一些重要模組:

協議功能用處埠號Python 模組
HTTP網頁訪問80httplib, urllib, xmlrpclib
NNTP閱讀和張貼新聞文章,俗稱為"帖子"119nntplib
FTP檔案傳輸20ftplib, urllib
SMTP傳送郵件25smtplib
POP3接收郵件110poplib
IMAP4獲取郵件143imaplib
Telnet命令列23telnetlib
Gopher資訊查詢70gopherlib, urllib

更多內容可以參閱官網的 Python Socket Library and Modules。