本篇文章將為讀者講解如何使用Python監聽端口并獲取數據,讓你在網絡編程方面又會進一步的提升。
一、監聽端口基礎知識
在計算機網絡中,一個端口(Port)是一個可與網絡上其他設備通信的邏輯地址。常用的端口號有FTP服務使用的21端口,Web服務使用的80端口,SSH遠程登錄服務使用的22端口等等。
在Python中,最常用的網絡編程套接字(socket)中,套接字的屬性中,這個端口號由變量SOL_SOCKET的SO_REUSEADDR選項所確定。
import socket
HOST = '0.0.0.0'
PORT = 8888
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print(f'Connected by {addr}')
while True:
data = conn.recv(1024)
print(f'Received {data}')
break
conn.close()
二、監聽端口實例解析
上述示例代碼中我們首先使用了Python標準庫中的socket模塊創建了一個套接字對象s,我們可以通過socket.socket()函數來實現。第一個參數AF_INET是IPv4,第二個參數SOCK_STREAM表示TCP連接。
在這里,我們需要指定我們的IP地址和端口號以便在服務器端監聽到這個地址和端口的數據。HOST設置為空字符串時,表示接收任何IP地址的客戶端數據。端口號使用整數類型,常用的端口數范圍在0~1023之間。
通過sock.bind()函數將我們的主機和端口綁定在一起,這樣我們的服務器端就可以監聽到這個端口了。
我們的服務器端在conn, addr = s.accept()這里進行等待客戶端的連接。如果客戶端連接成功,則通過conn, addr獲取到客戶端的連接信息。這里的conn代表一個新的套接字對象用于通信,addr是客戶端地址。我們就可以在這里進行一系列的數據處理了。
當我們處理完畢后,通過conn.close()來關閉連接。
三、使用多任務處理請求
在現實應用中,我們的服務器端需要同時處理多個客戶端的請求。這時我們可以使用多任務來提高服務器端的并發能力,Python也提供了多種多任務編程的方式幫助我們達到這個目的。
下面我們舉一個例子, 演示如何使用多線程來實現多客戶端同時請求。
import socket
import threading
def handle_client(conn, addr):
while True:
data = conn.recv(1024)
if not data:
break
print(f'{addr[0]}:{addr[1]} says {data.decode()}')
conn.close()
def receive_thread(s):
while True:
conn, addr = s.accept()
print(f'Connected by {addr}')
client_thread = threading.Thread(target=handle_client, args=(conn,addr))
client_thread.start()
def main():
HOST = '0.0.0.0'
PORT = 8888
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(5)
print(f'Server listening on {HOST}:{PORT}')
receive_thread(s)
if __name__ == '__main__':
main()
在這個服務器端程序中,我們通過函數handle_client實現了對于發送信息的客戶端的數據處理。while True表示我們在等待客戶端數據的過程中,持續不斷地將客戶端傳來的數據按照我們在conn中獲取的客戶端信息寫入到終端中,這樣我們就能同時對于不同客戶端的信息進行處理了。
通過receive_thread函數,我們持續地在監聽著服務器端與客戶端的連接。按照我們上述所講的,每當有一個客戶端的連接被建立后,我們跳轉到client_thread,實現對于客戶端連接的處理。
四、來自外部流數據的獲取
在服務器端我們可以通過socket模塊中的recv()方法實現對于來自客戶端的流數據的實時獲取,如果是文件系統中已有的文件,我們可以通過文件讀取器實現對于文件的實時讀取,和操作。
在本例中,我們實現了http流數據的獲取和處理, 這在爬蟲和大規模數據處理方面有一定的用途。
import socket
class Rocker:
def __init__(self, host='127.0.0.1', port=2333):
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind((host, port))
print(f'Server started at {host}:{port}.')
self.server.listen()
def handle_client(self, client, address):
print(f"Accepted connection from {address}")
data = b''
while True:
buffer = client.recv(4096)
if not buffer:
break
data += buffer
client.close()
print(f"Closed connection from {address}")
def run(self):
while True:
client, address = self.server.accept()
cthread = threading.Thread(target=self.handle_client, args=(client, address))
cthread.start()
if __name__ == "__main__":
rocker = Rocker()
rocker.run()
在上述實例中,我們首先使用Python標準套接字模塊socket中的socket()函數創建一個套接字實例,并且把該實例綁定在本地的IP地址以及端口號為2333上。當客戶機請求連接上來的時候,服務器輸入“Accepted connection from {address}”來提示客戶端已經建立連接,然后就開始接受客戶機發送過來的數據,當客戶機沒有數據需要發送的時候,服務器關閉連接并打印“Closed connection from {address}”來提示客戶端和服務器的連接已經斷開。
五、解析SUMMARY
在實際開發中,經常會遇到需要監聽網絡端口并獲取數據的情況。本文介紹了在Python語言中通過使用socket模塊來實現這個目標。同時本文還補充了多個示例,幫讀者在應用Python進行網絡編程的時候,更加深入地了解監聽端口在實際應用中的運用和細節,讓讀者對Python的網絡編程有了更加清晰的認識。