python中的tcp


TCP簡介

TCP介紹

TCP協議,傳輸控制協議(英語:Transmission Control Protocol,縮寫為 TCP)是一種面向連接的、可靠的、基於字節流的傳輸層通信協議,由IETF的RFC 793定義。

TCP通信需要經過創建連接、數據傳送、終止連接三個步驟。

TCP通信模型中,在通信開始之前,一定要先建立相關的鏈接,才能發送數據,類似於生活中,"打電話""

TCP特點

1. 面向連接

通信雙方必須先建立連接才能進行數據的傳輸,雙方都必須為該連接分配必要的系統內核資源,以管理連接的狀態和連接上的傳輸。

雙方間的數據傳輸都可以通過這一個連接進行。

完成數據交換后,雙方必須斷開此連接,以釋放系統資源。

這種連接是一對一的,因此TCP不適用於廣播的應用程序,基於廣播的應用程序請使用UDP協議。

2. 可靠傳輸

1)TCP采用發送應答機制

TCP發送的每個報文段都必須得到接收方的應答才認為這個TCP報文段傳輸成功

2)超時重傳

發送端發出一個報文段之后就啟動定時器,如果在定時時間內沒有收到應答就重新發送這個報文段。

TCP為了保證不發生丟包,就給每個包一個序號,同時序號也保證了傳送到接收端實體的包的按序接收。然后接收端實體對已成功收到的包發回一個相應的確認(ACK);如果發送端實體在合理的往返時延(RTT)內未收到確認,那么對應的數據包就被假設為已丟失將會被進行重傳。

3)錯誤校驗

TCP用一個校驗和函數來檢驗數據是否有錯誤;在發送和接收時都要計算校驗和。

  1. 流量控制和阻塞管理

流量控制用來避免主機發送得過快而使接收方來不及完全收下。

TCP與UDP的不同點

  • 面向連接(確認有創建三方交握,連接已創建才作傳輸。)
  • 有序數據傳輸
  • 重發丟失的數據包
  • 舍棄重復的數據包
  • 無差錯的數據傳輸
  • 阻塞/流量控制

udp通信模型

udp通信模型中,在通信開始之前,不需要建立相關的鏈接,只需要發送數據即可,類似於生活中,"寫信""

TCP通信模型

udp通信模型中,在通信開始之前,一定要先建立相關的鏈接,才能發送數據,類似於生活中,"打電話""

tcp客戶端

tcp的客戶端要比服務器端簡單很多,如果說服務器端是需要自己買手機、查手機卡、設置鈴聲、等待別人打電話流程的話,那么客戶端就只需要找一個電話亭,拿起電話撥打即可,流程要少很多

python創建tcp客戶端的代碼如下:

import socket


def main():
        # 1.創建套接字socket
        tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        # 2.連接服務器
        dest_ip = input("請輸入服務器ip:")
        dest_port = int(input("請輸入服務器port:"))
        dest_addr = (dest_ip, dest_port)
        tcp_socket.connect(dest_addr)

        # 3. 接收/發送數據
        send_data = input("請輸入要發送的數據:")
        tcp_socket.send(send_data.encode("utf-8"))    
    
        # 接收服務器發送的數據
        recv_data = tcp_socket.recv(1024)
        print(recv_data.decode("utf-8"))    

        # 4. 關閉套接字socket
        tcp_socket.close()

if __name__ == "__main__":

        main()

在ubuntu的終端上執行:

在網絡調試助手中啟動tcp服務器進行交互:

tcp服務器

在程序中,如果想要完成一個tcp服務器的功能,需要的流程如下:

  1. socket創建一個套接字
  2. bind綁定ip和port
  3. listen使套接字變為可以被動鏈接
  4. accept等待客戶端的鏈接
  5. recv/send接收發送數據
import socket


def main():
        # 1.創建套接字
        tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
        # 2.綁定端口
        addr = ("", 8866)
        tcp_server_socket.bind(addr)

        # 3.監聽鏈接
        tcp_server_socket.listen(128)

        # 4.接收別人的連接
        # client_socket用來為這個客戶端服務
        client_socket, client_addr = tcp_server_socket.accept() 
    
        # 5.接收對方發送的數據
        recv_data = client_socket.recv(1024)    
        print("接收到的數據:%s" % recv_data.decode("utf-8"))
    
        # 6.給對方發送數據
        client_socket.send("hahaha".encode("utf-8"))    

        # 7.關閉套接字 
        client_socket.close()
        tcp_server_socket.close()


if __name__ == "__main__":
        main()

在ubuntu的終端上執行:

在網絡調試助手中啟動tcp服務器進行交互:

tcp注意點

  1. tcp服務器一般情況下都需要綁定,否則客戶端找不到這個服務器
  2. tcp客戶端一般不綁定,因為是主動鏈接服務器,所以只要確定好服務器的ip、port等信息就好,本地客戶端可以隨機
  3. tcp服務器中通過listen可以將socket創建出來的主動套接字變為被動的,這是做tcp服務器時必須要做的
  4. 當客戶端需要鏈接服務器時,就需要使用connect進行鏈接,udp是不需要鏈接的而是直接發送,但是tcp必須先鏈接,只有鏈接成功才能通信
  5. 當一個tcp客戶端連接服務器時,服務器端會有1個新的套接字,這個套接字用來標記這個客戶端,單獨為這個客戶端服務
  6. listen后的套接字是被動套接字,用來接收新的客戶端的鏈接請求的,而accept返回的新套接字是標記這個新客戶端的
  7. 關閉listen后的套接字意味着被動套接字關閉了,會導致新的客戶端不能夠鏈接服務器,但是之前已經鏈接成功的客戶端正常通信。
  8. 關閉accept返回的套接字意味着這個客戶端已經服務完畢
  9. 當客戶端的套接字調用close后,服務器端會recv解堵塞,並且返回的長度為0,因此服務器可以通過返回數據的長度來區別客戶端是否已經下線


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM