Python 的 Socket 模組提供便捷的網路程式設計介面,讓開發者能輕鬆建立 TCP 和 UDP 應用程式。建立 TCP 伺服器需使用 socket.SOCK_STREAM 引數,繫結 IP 和埠,並監聽連線請求。客戶端則需建立相同型別的 Socket 並連線到伺服器。UDP 通訊使用 socket.SOCK_DGRAM,透過 sendto() 和 recvfrom() 進行資料交換,無需建立連線。此外,Python 也提供 http.client 和 urllib.request 等模組,簡化 HTTP 請求的處理,讓開發者能更有效率地操作網頁內容。

使用Socket進行TCP客戶端與伺服器實作

在本章節中,我們將介紹如何使用Python的Socket模組來建立一個簡單的TCP客戶端與伺服器,以實作客戶端與伺服器之間的訊息傳遞。

使用Socket建立TCP伺服器

首先,我們需要建立一個Socket物件作為伺服器。以下是一個簡單的TCP伺服器實作範例:

import socket
import threading

SERVER_IP = "127.0.0.1"
SERVER_PORT = 9998

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

# 繫結IP與Port
server.bind((SERVER_IP, SERVER_PORT))

# 監聽連線請求
server.listen(5)
print("[*] Server Listening on %s:%d" % (SERVER_IP, SERVER_PORT))

def handle_client(client_socket):
    # 接收客戶端請求
    request = client_socket.recv(1024)
    print("[*] Received request : %s from client %s" % (request, client_socket.getpeername()))
    # 回傳確認訊息
    client_socket.send(bytes("ACK", "utf-8"))

while True:
    # 接受客戶端連線請求
    client, addr = server.accept()
    client.send("I am the server accepting connections...".encode())
    print("[*] Accepted connection from: %s:%d" % (addr[0], addr[1]))
    handle_client(client)
    client.close()

server.close()

內容解密:

  1. server = socket.socket(socket.AF_INET, socket.SOCK_STREAM):建立一個TCP Socket物件。
  2. server.bind((SERVER_IP, SERVER_PORT)):將Socket物件繫結到指定的IP與Port。
  3. server.listen(5):開始監聽連線請求,最大連線數為5。
  4. handle_client(client_socket):處理客戶端請求的函式,接收客戶端訊息並回傳確認訊息。

使用Socket建立TCP客戶端

接下來,我們需要建立一個Socket物件作為客戶端,以連線到上述的TCP伺服器。以下是一個簡單的TCP客戶端實作範例:

import socket

host = "127.0.0.1"
port = 9998

try:
    # 建立Socket物件
    mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 連線到伺服器
    mysocket.connect((host, port))
    print('Connected to host ' + str(host) + ' in port: ' + str(port))
    # 接收伺服器訊息
    message = mysocket.recv(1024)
    print("Message received from the server", message)
except Exception as e:
    print("Error:", e)

內容解密:

  1. mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM):建立一個TCP Socket物件。
  2. mysocket.connect((host, port)):連線到指定的伺服器IP與Port。
  3. message = mysocket.recv(1024):接收伺服器傳來的訊息。

圖示說明

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333

title 圖示說明

rectangle "連線請求" as node1
rectangle "接收請求" as node2
rectangle "回傳訊息" as node3

node1 --> node2
node2 --> node3

@enduml

此圖示說明瞭客戶端與伺服器之間的連線請求與訊息傳遞流程。

網路程式設計中的Socket應用:TCP與UDP協定實作

簡介

在網路程式設計中,Socket是用於實作不同主機之間通訊的重要工具。Python提供了強大的socket模組,使得開發者能夠輕鬆建立根據TCP或UDP協定的客戶端-伺服器架構應用程式。本篇文章將探討如何使用Python的socket模組來實作TCP和UDP協定下的訊息傳遞。

TCP協定下的Socket程式設計

TCP(傳輸控制協定)是一種導向連線的協定,能夠確保資料的可靠傳輸。在Python中,建立TCP Socket需要使用socket.SOCK_STREAM引數。

實作TCP伺服器

首先,我們來建立一個簡單的TCP伺服器。伺服器端程式碼如下:

import socket

SERVER_IP = "127.0.0.1"
SERVER_PORT = 6789

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((SERVER_IP, SERVER_PORT))
server_socket.listen(5)

print(f"[*] 伺服器監聽於 {SERVER_IP}:{SERVER_PORT}")

while True:
    client_socket, address = server_socket.accept()
    data = client_socket.recv(1024)
    print(f"收到來自 {address} 的訊息:{data.decode()}")

    response = "你好,客戶端!"
    client_socket.send(response.encode())
    client_socket.close()

實作TCP客戶端

接下來,建立一個TCP客戶端來與伺服器進行通訊。客戶端程式碼如下:

import socket

SERVER_IP = "127.0.0.1"
SERVER_PORT = 6789

client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((SERVER_IP, SERVER_PORT))

while True:
    message = input("輸入你的訊息 > ")
    client_socket.send(message.encode())
    if message == "quit":
        break
    response = client_socket.recv(1024)
    print(f"來自伺服器的回應:{response.decode()}")

client_socket.close()

程式碼解析

  1. 伺服器端

    • 使用socket.socket(socket.AF_INET, socket.SOCK_STREAM)建立TCP Socket。
    • bind()方法將Socket繫結到特定的IP和埠。
    • listen()方法使伺服器進入監聽狀態,準備接受客戶端連線。
    • accept()方法接受客戶端連線請求,並傳回客戶端Socket和地址。
  2. 客戶端

    • 同樣使用socket.socket(socket.AF_INET, socket.SOCK_STREAM)建立TCP Socket。
    • connect()方法用於連線伺服器。
    • 使用send()recv()方法進行資料傳輸。

UDP協定下的Socket程式設計

UDP(使用者資料報協定)是一種無連線的協定,不保證資料的可靠傳輸,但具有較高的傳輸效率。在Python中,建立UDP Socket需要使用socket.SOCK_DGRAM引數。

實作UDP伺服器

UDP伺服器端程式碼如下:

import socket

SERVER_IP = "127.0.0.1"
SERVER_PORT = 6789

server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind((SERVER_IP, SERVER_PORT))

print(f"[*] UDP伺服器監聽於 {SERVER_IP}:{SERVER_PORT}")

while True:
    data, address = server_socket.recvfrom(4096)
    print(f"收到來自 {address} 的訊息:{data.decode().strip()}")

    response = "你好,客戶端!"
    server_socket.sendto(response.encode(), address)

實作UDP客戶端

UDP客戶端程式碼如下:

import socket

SERVER_IP = "127.0.0.1"
SERVER_PORT = 6789

client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

address = (SERVER_IP, SERVER_PORT)

while True:
    message = input("輸入你的訊息 > ")
    if message == "quit":
        break
    client_socket.sendto(message.encode(), address)
    response, addr = client_socket.recvfrom(4096)
    print(f"來自伺服器的回應:{response.decode()}")

client_socket.close()

程式碼解析

  1. 伺服器端

    • 使用socket.SOCK_DGRAM建立UDP Socket。
    • 使用recvfrom()接收客戶端訊息,並使用sendto()回應客戶端。
  2. 客戶端

    • 同樣使用socket.SOCK_DGRAM建立UDP Socket。
    • 使用sendto()傳送訊息給伺服器,並使用recvfrom()接收伺服器回應。

HTTP程式設計

本章將介紹HTTP協定,並探討如何使用Python檢索和操作網頁內容。我們還將檢視標準的urllib函式庫,以及requestshttpx套件。此外,我們將介紹第三方requests模組,它是urllib的一個非常流行的替代方案,具有優雅的介面和強大的功能集,是簡化HTTP工作流程的絕佳工具。最後,我們將介紹HTTP身份驗證機制,以及如何使用requests模組進行管理。

本章將為我們提供在Python中使用不同模組來向Web服務或REST API發出請求的基礎。

本章涵蓋的主題

  • 介紹HTTP協定
  • 使用http.client建立HTTP客戶端
  • 使用urllib.request建立HTTP客戶端
  • 使用requests建立HTTP客戶端
  • 使用httpx建立HTTP客戶端
  • 使用Python進行身份驗證機制

技術需求

在開始閱讀本章之前,您應該具備Python程式設計的基礎知識,並對HTTP協定有一定的瞭解。我們將使用Python 3.7版本,可在www.python.org/downloads取得。

介紹HTTP協定

HTTP是一種應用層協定,定義了客戶端、代理伺服器和伺服器之間進行資訊交換的規則。它基本上由兩個元素組成:

  • 由客戶端發出的請求,向伺服器請求特定資源,該資源由URL指定。
  • 由伺服器發出的回應,提供客戶端請求的資源。

HTTP協定是一種無狀態的超文字資料傳輸協定,不會儲存客戶端和伺服器之間交換的資訊。由於它是一種無狀態的協定,因此需要使用其他技術來儲存交換資料,例如Cookie(儲存在客戶端的值)或Session(在伺服器端保留的臨時記憶體空間,用於儲存一個或多個HTTP交易的資訊)。

伺服器會傳回一個HTTP程式碼,指示客戶端請求的操作結果。此外,請求可以使用標頭在請求和回應中包含額外的資訊。

同樣重要的是要注意,HTTP協定在底層使用Socket來建立客戶端-伺服器連線。在Python中,我們可以使用更高層級的模組,它抽象了底層的Socket服務。

檢視狀態碼

每次向Web伺服器發出請求時,它都會接收並處理該請求,然後傳回所請求的資源以及HTTP標頭。HTTP回應的狀態碼指示特定的HTTP請求是否已成功完成。

我們可以使用其status屬性讀取回應的狀態碼。值200是一個HTTP狀態碼,告訴我們請求已成功:

>>> response.status
200

狀態碼分為以下幾類別:

  • 100:資訊
  • 200:成功
  • 300:重新導向
  • 400:客戶端錯誤
  • 500:伺服器錯誤

在300型別的程式碼中,我們可以找到302重新導向程式碼,它指示由location標頭給出的特定URL已被臨時移動,直接將它們導向新的位置。另一個我們可以找到的程式碼是307,它在瀏覽器檢測到URL正在使用HTTPS的情況下用作內部重新導向。

使用http.client建立HTTP客戶端

Python提供了一些模組來建立HTTP客戶端。主要的函式庫模組是http.clienturllib.request。這些模組具有不同的功能,但對於大多數的Web測試都很有用。我們還可以找到提供了對標準函式庫的一些改進的requests模組。要了解更多關於這些請求的資訊,請存取https://docs.python.org/3/library/http.client.html

讓我們首先了解http.client模組。 http.client模組定義了一個實作HTTPConnection類別的類別。此類別接受網域和埠作為引數。網域是必需的,而埠是可選的。此類別的一個例項表示與HTTP伺服器的交易。

範例程式碼

import http.client
connection = http.client.HTTPConnection("www.google.com")
connection.request("GET", "/")
response = connection.getresponse()
print(type(response))
print(response.status, response.reason)
if response.status == 200:
    data = response.read()
    print(data)

內容解密:

  1. http.client.HTTPConnection("www.google.com"):建立一個與www.google.com的HTTP連線。
  2. connection.request("GET", "/"):向伺服器發出GET請求,請求根目錄("/")。
  3. response = connection.getresponse():取得伺服器的回應。
  4. print(response.status, response.reason):列印回應的狀態碼和原因短語。
  5. if response.status == 200::檢查狀態碼是否為200(表示成功)。
  6. data = response.read():讀取回應的內容。
  7. print(data):列印回應的內容。

使用urllib.request建立HTTP客戶端

urllib.request套件是Python標準函式庫中推薦用於HTTP任務的套件。 urllib套件具有更簡單的介面,並且能夠管理與HTTP請求相關的所有任務。

範例程式碼

#! /usr/bin/env python3
import urllib.request
import urllib.parse

內容解密:

  1. import urllib.request:匯入urllib.request模組,用於處理HTTP請求。
  2. import urllib.parse:匯入urllib.parse模組,用於解析URL。

透過本章,我們學習瞭如何使用Python中的不同模組來建立HTTP客戶端,包括http.clienturllib.request。這些知識將幫助我們更好地理解和處理HTTP請求,為進一步探索網路程式設計打下堅實的基礎。