1. 網絡-tcp
參考
1.1 tcp簡介
介紹
TCP協議,傳輸控制協議(英語: Transmission Control Protocol, 縮寫為TCP)是一種面向連接的、可靠的、基于字節流的傳輸層通信協議,由IETF的RFC 793定義.
TCP通信需要經過創建連接、數據傳送、終止連接三個步驟.
TCP通信模型中,在通信開始之前,一定要先建立相關的鏈接,才能發送數據,類似于生活中的"打電話"
TCP特點
-
面向連接
- 通信雙方必須先建立連接才能進行數據的傳輸,雙方都必須為該連接分配必要的系統內核資源,以管理連接的狀態和連接上的傳輸。
- 雙方間的數據傳輸都可以通過這一個連接進行。
- 完成數據交換后,雙方必須斷開此連接,以釋放系統資源。
-
可靠傳輸
- TCP采用發送應答機制
- TCP發送的每個報文段都必須得到接收方的應答才認為這個TCP報文段傳輸成果
- 超時重傳
- 發送端發送一個報文段之和就啟動定時器,如果在定時時間內沒有收到應答就重新發送這個報文段
- TCP為了保證不發生丟包,就給每一個包一個序列號,同時序號也保證了傳送到接受端實體的包的按序接收
- 然后接收端實體對已接收到的包發回一個相應的確認(ACK);如果發送端實體在合理的往返時延(RTT)內未收到確認,那么對應的數據包就被假設為已丟失將會被重傳.
- 錯誤校驗
- TCP用一個校驗和函數來校驗數據是否有錯誤;在發送和接收時都要計算校驗和
- 流量控制和擁塞管理
- 流量控制用來避免主機發送得過快而使接收方來不及完全收下
- TCP采用發送應答機制
TCP與UDP的不同點
- 面向連接(確認有創建三方交流,連接已創建才作傳輸)
- 有序數據傳輸
- 重發丟失的數據包
- 舍棄重復的數據包
- 無差錯的數據傳輸
- 阻塞/流量控制
udp通信模型
udp通信模型中,在通信開始之前, 不需要建立相關的鏈接,只需要發送數據即可,類似于生活中的"寫信"
1.2 tcp網絡程序 - 客戶端(重點)
服務器就是提供服務的一方,客戶端就是需要被服務的一方
tcp客戶端
- 創建套接字
- 鏈接服務器
- 收發數據
- 關閉套接字
from socket import *def main:tcp_socket = socket(AF_INET, SOCK_STREAM)server_ip = input("請輸入要鏈接的ip: ")server_port = input("請輸入要鏈接的port: ")server_addr = (server_ip, server_port)tcp_socket.connect(server_addr)send_data = input("請輸入要發送的數據: ")tcp_socket.send(send_data.encode("gbk"))tcp_socket.close()if __name__ == "__main__":main()
1.3 tcp服務器
- socket創建一個套接字
- bind綁定ip和port
- listen使套接字變為可用被動鏈接
- recv/send接收發送數據
from socket import *def main():# 創建tcp套接字tcp_server_socket = socket(AF_INET, SOCK_STREAM)# 綁定端口tcp_server_socket.bind(("", 7890))# 將tcp變為被動監聽tcp_server_socket.listen(128)# 接線員獲取客戶端的套接字和地址(ip和端口號)new_client_socket, client_addr = tcp_server_socket.accept()# 使用新的套接字進行通信recv_data = new_client_socket.recv(1024) # 接收數據,最大為1024字節print(recv_data)# 返回數據new_client_socket.send("hahaha".encode("utf-8"))# 關閉套接字tcp_server_socket.close()new_client_socket.close()if __name__ == "__main__":main()
小結:
- tcp服務器,創建的套接字主要是用來監聽的
- 監聽得到新的交互的套接字(可用算是通道吧TuT)
1.3.1 為多個客戶端服務
同一時刻只能處理一個客戶端,但是多個客戶端同時連接,會按連接的順序進行阻塞~當一個客戶端處理完畢之后,會根據排隊順序處理后面的
from socket import *def main():# 創建tcp套接字tcp_server_socket = socket(AF_INET, SOCK_STREAM)# 綁定端口tcp_server_socket.bind(("", 7890))# 轉為被動監聽tcp_server_socket.listen(128)while True:print("等待一個新的客戶端的到來!")# 接收客戶端的套接字new_client_socket, client_addr = tcp_server_socket.accept()print("一個新的客戶端以及到來 %s" % str(client_addr))# 使用新的套接字進行收發數據recv_data = new_client_socket.recv(1024)print("客戶端發送過來的請求是: %s" % recv_data.decode("utf-8"))new_client_socket.send("Hello World".encode("utf-8"))# 關閉套接字new_client_socket.close()print("已經服務完畢...")tcp_server_socket.close()if __name__ == "__main__":main()
1.3.2 為多個客戶服務多次
from socket import *def main():tcp_sever_socket = socket(AF_INET, SOCK_STREAM)tcp_sever_socket.bind(("", 8080))tcp_sever_socket.listen(128)while True:print("等待客戶的到來...")new_socket, client_addr = tcp_sever_socket.accept()print("檢測到 %s 的到來" % str(client_addr))while True:recv_data = new_socket.recv(1024)if recv_data:print("收到信息 %s" % recv_data.decode("gbk"))new_socket.send("收到您的信息~".encode("gbk"))else:breaknew_socket.close()print("服務完畢...")tcp_server_socket.close()if __name__ == "__main__":main()