TCP:英文全拼(Transmission Control Protocol)簡稱傳輸控制協議,它是一種面向連接的、可靠的、基於字節流的傳輸層通信協議.
TCP通信需要經過創建連接、數據傳送、終止連接三個步驟。
TCP 特點
面向連接
通信雙方必須先建立連接才能進行數據的傳輸,雙方都必須為該連接分配必要的系統內核資源,以管理連接的狀態和連接上的傳輸。
雙方間的數據傳輸都可以通過這一個連接進行。
完成數據交換后,雙方必須斷開此連接,以釋放系統資源。
這種連接是一對一的,因此TCP不適用於廣播的應用程序,基於廣播的應用程序請使用UDP協議。
可靠傳輸
TCP采用發送應答機制
TCP發送的每個報文段都必須得到接收方的應答才認為這個TCP報文段傳輸成功
超時重傳
發送端發出一個報文段之后就啟動定時器,如果在定時時間內沒有收到應答就重新發送這個報文段。
TCP為了保證不發生丟包,就給每個包一個序號,同時序號也保證了傳送到接收端實體的包的按序接收。然后接收端實體對已成功收到的包發回一個相應的確認(ACK);如果發送端實體在合理的往返時延(RTT)內未收到確認,那么對應的數據包就被假設為已丟失將會被進行重傳。
錯誤校驗
由發送端計算,然后由接收端驗證,其目的是為了檢測數據在發送端到接收端之間是否有改動,如果接收方檢測到校驗和有差錯,則直接丟棄這個數據包。
流量控制和阻塞管理
流量控制用來避免主機發送得過快而使接收方來不及完全收下。
TCP 網絡程序流程
TCP 優缺點
優點:可靠,穩定
適合傳輸大量數據
缺點:傳輸速度慢 、
占用系統資源高
TCP 使用場景
當對網絡通訊質量有要求的時候,比如:整個數據要准確無誤的傳遞給對方,這往往用於一些要求可靠的應用,比如HTTP、HTTPS、FTP等傳輸文件的協議,POP、SMTP等郵件傳輸的協議。
UDP 網絡程序流程
UDP 網絡程序發送數據不需要建立連接
TCP與UDP的小例子(Python)
TCP客戶端 client
import socket
from pip._vendor.distlib.compat import raw_input
target_host = "127.0.0.1"
target_port = 9999
#建立一個socket 對象
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 鏈接客戶端
client.connect((target_host,target_port))
# print("connect%s %d" %(target_host,target_port))
while True:
data = raw_input('>')
client.send(data)
data = client.recv(1024)
if not data:
break
print(data)
TCP服務端server
import socket bind_ip="0.0.0.0" bind_port = "9999" server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) server.bind((bind_ip,bind_port)) server.listen(5) try: while True: client,add = server.accept() print("[*]你監聽的是:%s:%d" %(add[0],add[1])) while True: data = client.recv(1024) if not data: break print(data) data = raw_input('>') client.send(data) print(data) else: client.close() except Exception as e: print(e) server.close()
UDP 客戶端 client
import socket PORT =5555 HOST = '127.0.0.1' s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) data = "hello UDP".encode() s.sendto(data,(HOST,PORT)) print(s.recv(1024)) print('Send:%s to %s:%s ' %(data,HOST,PORT)) s.close()
UDP 服務端 server
import socket PORT =5555 HOST = '127.0.0.1' s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) s.bind((HOST,PORT)) while True: data,addr = s.recvfrom(1024) print("Receive %s" %(data.decode(),addr)) # s.sendto("Hello".encode()+data,addr)