網路程式通訊的流程

JJJhr發表於2024-06-18

網路程式通訊的流程:

1.透過ip地址找到網路中的裝置

2.透過埠號找到對應程序的埠

3.傳輸資料時還需要使用傳輸協議(TCP),保證資料的可靠性

4.socket完成程序之間網路資料的傳輸

ip地址的介紹

  IP地址是網際網路協議地址(Internet Protocol Address)的縮寫,用於在IP網路中唯一標識一個裝置。它通常由四個數字組成,每個數字在0-255之間,用點號分隔。IP地址分為IPv4和IPv6兩種版本,其中IPv4是目前廣泛使用的版本。

埠和埠號的介紹

  埠是計算機上用於接收和傳送資料的介面。每個埠都有一個唯一的埠號,用於標識和區分不同的服務或應用程式。常見的埠號有HTTP(80)、HTTPS(443)、FTP(21)等。

tcp的介紹

1.透過ip地址找到網路中的裝置

2.透過埠號找到對應程序的埠

3.傳輸資料時還需要使用傳輸協議(TCP),保證資料的可靠性

4.socket完成程序之間網路資料的傳輸

socket的介紹

  程序之間通訊的一個工具。Socket是網路程式設計中用於程序間通訊的一個抽象層,它提供了對TCP/IP、UDP等網路通訊協議的封裝。透過Socket,應用程式可以傳送和接收資料,實現不同計算機之間的通訊。

tcp網路應用程式的開發流程

tcp客戶端程式開發

  • 建立Socket物件。
  • 連線到伺服器(指定IP地址和埠號)。
  • 傳送和接收資料。
  • 關閉連線。
import socket

if __name__ == '__main__':
    # 1.建立tcp客戶端套接字
    # socket.AF_INET:ipv4
    # socket.SOCK_STREAM:tcp傳輸協議
    tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 2.和服務端套接字建立連線
    tcp_client_socket.connect(('192.168.198.1', 8080))

    # 3.傳送資料到服務端
    send_content = "請輸入要傳輸的資料"
    send_data = send_content.encode('utf-8')
    tcp_client_socket.send(send_data)

    # 4.接收服務端的資料
    recv_data = tcp_client_socket.recv(1024)
    print(recv_data.decode('utf-8'))
    # 5.關閉套接字
    tcp_client_socket.close()

tcp服務端的程式開發

  • 建Socket物件。
  • 繫結IP地址和埠號。
  • 開始監聽連線請求。
  • 接受客戶端連線。
  • 傳送和接收資料。
  • 關閉連線。
import socket

if __name__ == "__main__":
    # 1.建立TCP服務端套接字
    tcp_server_socket  = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 2.繫結埠號
    # ip地址一般不用指定,表示本機的任何一個ip即可
    tcp_server_socket.bind(('', 8080))
    # 3.設定監聽
    # 128表示最大等待建立連線的個數
    tcp_server_socket.listen(128)
    # 4.等待接收客戶端的連線請求
    # 注意點:每次當客戶端和伺服器端建立連線成功都會返回一個新的套接字
    # tcp_server_socket只負責等待接收客戶端建立連線成功,收發訊息不使用該套接字
    new_client, ip_port = tcp_server_socket.accept()
    print("客戶端的ip地址個埠號為:", ip_port)
    # 5.接收資料
    # 收發資訊都使用返回的這個新的套接字
    recv_data = new_client.recv(1024)
    # 對二進位制資料進行解碼變成字串
    recv_content = recv_data.decode("gbk")
    print("接受的資料為:", recv_content)
    # 6.傳送資料到客戶端
    send_content = "問題正在處理中..."
    # 對字串進行編碼
    send_data = send_content.encode("gbk")
    new_client.send(send_data)
    # 關閉服務與客戶端的套接字,表示和客戶端終止通訊
    new_client.close()
    # 7.關閉服務端套接字,表示服務端以後不在等待接收客戶端的連線請求
    tcp_server_socket.close()

設定埠號複用

  在某些情況下,伺服器程式可能需要在程式重啟時立即使用之前繫結的埠號。這時可以設定埠號複用(SO_REUSEADDR)選項,允許伺服器程式立即重新繫結到該埠。

import socket

if __name__ == "__main__":
    # 1.建立TCP服務端套接字
    tcp_server_socket  = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 設定埠號複用,表示意思:服務端程式退出埠號立即釋放
    # 1.SOL_SOCKET:表示當前套接字
    # 2.SO_REUSEADDER:表示複用埠號的選項
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,True)
    # 2.繫結埠號
    # ip地址一般不用指定,表示本機的任何一個ip即可
    tcp_server_socket.bind(('', 8080))
    # 3.設定監聽
    # 128表示最大等待建立連線的個數
    tcp_server_socket.listen(128)
    # 4.等待接收客戶端的連線請求
    # 注意點:每次當客戶端和伺服器端建立連線成功都會返回一個新的套接字
    # tcp_server_socket只負責等待接收客戶端建立連線成功,收發訊息不使用該套接字
    new_client, ip_port = tcp_server_socket.accept()
    # 程式碼執行到此,說明客戶端和伺服器建立連線成功
    print("客戶端的ip地址個埠號為:", ip_port)
    # 5.接收客戶端對的資料
    # 收發資訊都使用返回的這個新的套接字
    recv_data = new_client.recv(1024)
    print("接收的資料長度為:",len(recv_data))
    # 對二進位制資料進行解碼變成字串
    recv_content = recv_data.decode("gbk")
    print("接受的資料為:", recv_content)

    send_content = "問題正在處理中..."
    # 對字串進行編碼
    send_data = send_content.encode("gbk")
    # 6.傳送資料到客戶端
    new_client.send(send_data)
    # 關閉服務與客戶端的套接字,表示和客戶端終止通訊
    new_client.close()
    # 7.關閉服務端套接字,表示服務端以後不在等待接收客戶端的連線請求
    tcp_server_socket.close()

tcp網路應用程式的注意點

  • 併發處理:服務端需要能夠同時處理多個客戶端的連線請求和資料傳輸。
  • 異常處理:在網路程式設計中,網路故障、連線中斷等異常情況時有發生,需要編寫健壯的異常處理程式碼。
  • 資源管理:合理管理Socket資源、記憶體資源等,避免資源洩漏和效能問題
  • 當 TCP 客戶端程式想要和 TCP 服務端程式進行通訊的時候必須要先建立連線
  • TCP 客戶端程式一般不需要繫結埠號,因為客戶端是主動發起建立連線的。
  • TCP 服務端程式必須繫結埠號,否則客戶端找不到這個 TCP 服務端程式。
  • listen 後的套接字是被動套接字,只負責接收新的客戶端的連線請求,不能收發訊息。
  • 當TCP 客戶端程式和 TCP 服務端程式連線成功後,TCP 伺服器端程式會產生一個新的套接字,收發客戶端訊息使用該套接字。
  • 關閉 accept 返回的套接字意味著和這個客戶端已經通訊完畢。
  • 關閉 listen 後的套接字意味著服務端的套接字關閉了,會導致新的客戶端不能連線服務端,但是之前已經接成功的客戶端還能正常通訊。
  • 當客戶端的套接字呼叫 close後,伺服器端的recv 會解阻塞,返回的資料長度為0,服務端可以透過8.返回資料的長度來判斷客戶端是否已經下線,反之服務端關閉套接字,客戶端的recv 也會解阻塞,返回的資料長度也為0。

多人版tcp服務端程式

  多人版TCP服務端程式需要能夠同時處理多個客戶端的連線請求和資料傳輸。這通常需要使用多執行緒或多程序技術來實現併發處理。每個客戶端連線都由一個單獨的執行緒或程序負責處理,從而實現多人同時線上通訊。

import socket

if __name__ == "__main__":
    # 1.建立TCP服務端套接字
    tcp_server_socket  = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 設定埠號複用,表示意思:服務端程式退出埠號立即釋放
    # 1.SOL_SOCKET:表示當前套接字
    # 2.SO_REUSEADDER:表示複用埠號的選項
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,True)
    # 2.繫結埠號
    # ip地址一般不用指定,表示本機的任何一個ip即可
    tcp_server_socket.bind(('', 8080))
    # 3.設定監聽
    # 128表示最大等待建立連線的個數
    tcp_server_socket.listen(128)
    # 4.等待接收客戶端的連線請求
    # 注意點:每次當客戶端和伺服器端建立連線成功都會返回一個新的套接字
    # tcp_server_socket只負責等待接收客戶端建立連線成功,收發訊息不使用該套接字
    # 迴圈等待接收客戶端的連線請求
    while True:
        new_client, ip_port = tcp_server_socket.accept()
        # 程式碼執行到此,說明客戶端和伺服器建立連線成功
        print("客戶端的ip地址個埠號為:", ip_port)
        # 5.接收客戶端對的資料
        # 收發資訊都使用返回的這個新的套接字
        recv_data = new_client.recv(1024)
        print("接收的資料長度為:",len(recv_data))
        # 對二進位制資料進行解碼變成字串
        recv_content = recv_data.decode("gbk")
        print("接受的資料為:", recv_content)

        send_content = "問題正在處理中..."
        # 對字串進行編碼
        send_data = send_content.encode("gbk")
        # 6.傳送資料到客戶端
        new_client.send(send_data)
        # 關閉服務與客戶端的套接字,表示和客戶端終止通訊
        new_client.close()
    # 7.關閉服務端套接字,表示服務端以後不在等待接收客戶端的連線請求
    tcp_server_socket.close()

socket之send和recv的原理剖析

  • send:在TCP中,send函式用於向連線的對端傳送資料。資料被封裝在TCP報文中,透過網路傳輸到對端。send函式在資料被成功寫入傳送緩衝區後返回,但並不意味著資料已經被對端接收。
  • recv:recv函式用於從連線的對端接收資料。它從接收緩衝區中讀取資料,並返回給呼叫者。如果接收緩衝區中沒有資料

相關文章