傳輸層協議、應用層、socket套接字、半連結池

认真的六六發表於2024-06-20

【傳輸層協議TCP/UDP】

 1 PORT協議(埠協議)
 2     埠號用來(ip+port):標識一臺計算機上面的某一個應用程式
 3     埠號的範圍:0-65535
 4     這是因為傳輸層的協議:TCP、UDP等,它們的報頭埠號長度是16bit所決定的!! 2的16次方
 5     埠號特徵:動態分配(類似於洗浴中心號碼牌)
 6     每一個應用程式都要有一個埠號!!!
 7 
 8 ----------------------------------------------------------
 9 
10 # 建議:
11 0-1024    系統預設需要使用的埠號,作業系統裡面有一些固定的底層服務需要用的。別使用這些埠號!!
12 1024-8000    常見軟體的埠號,可能已經被佔掉了,也儘量別用!
13 8000之後的    以後寫專案推薦使用!!!
14 
15 軟體在啟動的時候是可以指定埠號的,就是說自己可以去指定用哪個埠號的,常用的已經被指定完了,
16 不指定一個埠號,就會被計算機動態的分配一個埠號!!!
17 
18 注意,埠號是不固定的,即可以由使用者手工可以分配(當然,一般在軟體編寫時就已經定義)。
19 當然,有很多應用軟體有公認的預設的埠,比如FTP:20和21,HTTP:80,TELNET:23等等
20 一個軟體可以擁有多個埠號,這證明這個軟體擁有不止一個網路功能。
21 
22 ------------------------------------------------
23 URL:統一資源定位符(網址)
24 網址本質是有IP和PORT組成的!!!!
25 
26 ------
27 
28 IP:PORT:能夠定位全世界獨一無二的一臺計算機上面的某一個應用程式
29     114.55.205.139:80
30 ------
31 
32 我們之所以不直接使用IP+PORT的原因是太難記 所以發明了域名(網址)
33 域名解析:將網址解析成IP+PORT

---------------------------------------------

重點!!!!!!

 1 # TCP與UDP都是用來規定通訊方式的
 2 
 3 TCP協議(傳輸控制協議)
 4     當應用程式希望透過 TCP 與另一個應用程式通訊時,它會傳送一個通訊請求。
 5     這個請求必須被送到一個確切的地址。在雙方“握手”之後,TCP 將在兩個應用程式之間建立
 6     一個全雙工 (full-duplex) 的通訊。這個全雙工的通訊將佔用兩個計算機之間的通訊線路,
 7     直到它被一方或雙方關閉為止。
 8     tcp協議就是控制資料資料包在傳輸過程中的規範格式
 9     是一種面向連線的,可靠的,基於位元組流的傳輸層協議。
10 
11 
12 (Transmission Control Protocol)傳輸控制協議
13 通俗地說TCP就是對於傳輸、傳送、通訊進行控制的協議。
14 
15 
16 1.TCP協議(重要)
17 TCP協議的特點是:面向連線、位元組流、可靠傳輸
18 TCP的機制具有:校驗機制、可靠、資料傳輸穩定
19 
20 ---------------------------------------------
21 # 三次握手:建連結
22     1.TCP協議也稱為可靠協議(資料不容易丟失)
23         造成資料不容易丟失的原因不是因為有雙向通道,而是因為有反饋機制!!!!!
24         給對方發訊息之後會保留一個副本 直到對方回應訊息收到了才會刪除
25         否則會在一定的時間內反覆傳送
26 
27 
28     2.洪水攻擊
29         同一時間有大量的客戶端請求建立連結,會導致服務端一直處於SYN_RCVD狀態!!!!
30     3.服務端如何區分客戶端建立連結的請求
31         可以對請求做唯一標識
32 ---------------------------------------------
33 
34 # 四次揮手:斷連結
35     1.四次不能合併為三次
36         因為中間需要確認訊息是否發完(TIME_WAIT)
37 
38 ---------------------------------------------
39 ps:課下可以深入研究一下TCP圖片上每個狀態的具體情況
40 
41 需要注意:
42 TCP協議用於1對1,即不能用於基於廣播和多播的應用程式
43 TCP連線雙方的收發資料次數不一定相同,即傳送多次的資料包,可能會被對方1次全部接收
44 TCP在傳送資料包後,必須得到接收方的應答,才認為傳輸成功,所以是可靠的
45 TCP採用超時重傳機制,超過時間沒收到應答,就會重新傳送。

(三次握手)

三次握手建立通道:建立連結是為了傳資料做準備的,三次握手即可
    1.客戶端傳送syn包---->伺服器
    2.伺服器收到syn包,傳送ack確認包---->客戶端
    3.客戶端收到ack確認包,傳送ack確認包---->伺服器
    三次握手完畢,建立雙向通道


(四次揮手)

   四次揮手斷開通道:斷開連結是為了節省資源做準備的,四次揮手即可
    1.客戶端傳送fin包---->伺服器
    2.伺服器收到fin包,傳送ack確認包---->客戶端
    3.伺服器傳送fin包---->客戶端
    4.客戶端收到fin包,傳送ack確認包---->伺服器
    四次揮手完畢,斷開雙向通道


PS補充:

1 PS:當服務端大量處於TIME_WAIT狀態時,會導致埠資源耗盡,無法建立新的連結
2    基於udp協議通訊:不需要建立雙向通訊的通道
3     C<--------------------S
4     S<--------------------C
5     udp協議:不可靠傳輸,速度快,但是容易丟包

tcp半連結池:(相當於一個等待服務視窗:如網上客服諮詢等待)backlog

【連結請求1,連結請求2,連結請求3.。。】

【應用層】

應用層相當於是程式設計師自己寫的應用程式,裡面的協議非常的多

常見的有:HTTP、HTTPS、FTP

ps:後續框架部分再做介紹

【socket套接字】

socket是網路通訊中的一個抽象概念,它是一個通訊鏈的控制代碼,可以用來實現不同主機之間的程序通訊
  import socket

 1 如果我們需要編寫基於網路進行資料互動的程式
 2 意味著我們需要自己透過程式碼來控制我們之前所學習的OSI七層(很繁瑣 很複雜 類似於我們自己編寫作業系統)
 3 
 4 socket類似於作業系統 封裝了醜陋複雜的介面提供簡單快捷的介面
 5 -----------------------------------------
 6 
 7 理解socket
 8 Socket是應用層與TCP/IP協議族通訊的中間軟體抽象層,它是一組介面。在設計模式中,
 9 Socket其實就是一個門面模式,它把複雜的TCP/IP協議族隱藏在Socket介面後面,對使用者來說,
10 一組簡單的介面就是全部,讓Socket去組織資料,以符合指定的協議。
11 
12 -----------------------------------------
13 
14 Socket其實就是一個門面模式,它把複雜的TCP/IP協議族隱藏在Socket介面後面,對使用者來說,
15 一組簡單的介面就是全部,讓Socket去組織資料,以符合指定的協議。
16 
17 -----------------------------------------
18 
19 socket也叫套接字
20     基於檔案型別的套接字家族(單機)
21     AF_UNIX
22 -------------
23     基於網路型別的套接字家族(聯網)
24     AF_INET
25 
26 -----------------------------------------
27 
28 在這裡主要學習利用socket完成TCP/IP通訊,首先需要生成兩個物件,
29 一個是客戶端(client),一個是服務端(sever)。

(工作流程)

(基於tcp協議的簡單套接字)

  PS:為什麼要先執行服務端,再執行客戶端?
      因為客戶端需要連線服務端,所以服務端必須先執行起來,等待客戶端的連線。
      而客戶端是主動連線服務端的,所以客戶端可以先執行起來。

 1 服務端
 2 
 3 import socket
 4 
 5 # 1.買手機
 6 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # AF_INET:表示ipv4,SOCK_STREAM:表示使用tcp協議
 7 
 8 # 2.繫結手機卡  ip+埠,如果ip是:0.0.0.0,表示本機的所有ip都可以使用
 9 phone.bind(("127.0.0.1", 8082))  # (繫結的是服務端的id)0-65535,1024以前的被系統保留使用
10 
11 #  3.開機,監聽狀態
12 phone.listen(5)  # 5表示半連結池的大小(backlog=5)
13 print('服務端啟動完成,監聽地址為:%s:%s' % (socket.gethostname(), 8082))
14 
15 # 4.等待電話連結請求
16 # conn:表示與客戶端進行通訊的socket,client_addr:表示客戶端的ip和埠
17 conn, client_addr = phone.accept()
18 print(conn)
19 print('客戶端的ip和埠:', client_addr)
20 
21 # 5.接收訊息\傳送訊息
22 data = conn.recv(1024)  # 1024表示一次接收1024個位元組
23 print('客戶端傳送的資料:', data.decode('utf-8'))
24 conn.send(data.upper())  # 將接收到的資料轉換為大寫,併傳送給客戶端
25 
26 # 6.關閉連線
27 conn.close()
28 
29 # 7.關閉手機(可選操作,可有可無)
30 phone.close()
31 
32 
33 -------------------------------------------------------------------------------------
34 客戶端
35 
36 
37 import socket
38 
39 
40 # 1.買手機:AF_INET--地址家族,實現網路通訊  SOCK_STREAM---基於什麼協議:流式協議(tcp)
41 # SOCK_DGRAM---資料包協議(udp)
42 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
43 
44 # 2.撥通服務端電話,傳送連線請求
45 phone.connect(('127.0.0.1', 8082))  # connect()括號裡是服務端ip和埠號=client_addr
46 
47 # 3.通訊
48 phone.send('hello tank 早上好'.encode('utf-8'))
49 
50 # 4.關閉連線,對應的是服務端的conn
51 phone.close()

(通訊迴圈--解決Bug)

 1 # 5.接收訊息\傳送訊息
 2 while True:
 3     try:
 4         data = conn.recv(1024)  # 1024表示本次接收的最大位元組數,收到的是bytes型別
 5         if len(data) == 0:
 6             # 在unix/linux下,一旦data收到的是空,就意味著是一種異常的行為:客戶端非法斷開了連結
 7             break
 8         print('客戶端發來的訊息:', data.decode('utf-8'))
 9         conn.send(data.upper())
10     except Exception:
11         # 針對windows系統客戶端非法斷開解決辦法
12         break
13 
14 --------------------------------------------------
15 客戶端
16 
17 # 3.通訊
18 # 客戶端如果強行斷開連線,會造成服務端死迴圈
19 while True:
20     msg = input('輸入要傳送的訊息>>:').strip()
21     #  輸入空格,不傳送,如果輸入空,客戶端會阻塞
22     if len(msg) == 0: continue
23     # 退出迴圈
24     # if msg == 'quit': break
25     # time.sleep(2)
26     # phone.send(b.ini'hello')  # phone.send('hello'.encode('utf-8')),必須是bytes型別
27     phone.send(msg.encode('utf-8'))
28     print('=====?')  # 驗證什麼造成了阻塞,阻塞在哪裡
29     data = phone.recv(1024)  # 上面一行程式碼執行,說明收阻塞了
30     print(data.decode('utf-8'))

(連結迴圈案例)

服務端應該滿足的特點:
  1.一直提供服務
  2.併發的提供服務

 1 服務端
 2 
 3 import socket
 4 
 5 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 6 
 7 # 2.繫結手機卡
 8 phone.bind(("127.0.0.1", 8083))
 9 
10 #  3.開機
11 phone.listen(5)
12 print('服務端啟動完成,監聽地址為:%s:%s' % (socket.gethostname(), 8083))
13 
14 # 4.等待電話連結請求,拿到電話連線conn
15 # 當上一客戶服務完成,接待下一個客戶的做法:
16 # 連結迴圈
17 while True:
18     conn, client_addr = phone.accept()
19     print('客戶端的ip和埠:', client_addr)
20 
21     # 5.接收訊息\傳送訊息
22     while True:
23         try:
24             data = conn.recv(1024)
25             if len(data) == 0:
26                 break
27             print('客戶端發來的訊息:', data.decode('utf-8'))
28             conn.send(data.upper())
29         except Exception:
30             # 針對windows系統客戶端非法斷開解決辦法
31             break
32 
33     # 6.關閉連線
34     conn.close()
35 
36 # 7.關閉手機
37 phone.close()
38 
39 
40 ------------------------------------------------------------------------------------
41 客戶端1:
42 
43 import socket
44 import time
45 
46 
47 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
48 
49 # 2.撥通服務端電話
50 phone.connect(('127.0.0.1', 8083))
51 
52 # 3.通訊迴圈
53 while True:
54     msg = input('輸入要傳送的訊息>>:').strip()
55     if len(msg) == 0: continue
56     # 退出迴圈
57     # if msg == 'quit': break
58     # time.sleep(2)
59     # phone.send(b.ini'hello')  # phone.send('hello'.encode('utf-8')),必須是bytes型別
60     phone.send(msg.encode('utf-8'))
61     print('=====?')
62     data = phone.recv(1024)
63     print(data.decode('utf-8'))
64 
65 # 4.關閉連線
66 phone.close()
67 
68 
69 
70 ===========================================
71 當其中一個客戶端斷開連線,第二個客戶端傳送建立連線請求,服務端能繼續服務

【半連結池】

 1 定義:
 2 半連線池是一個容器或機制,用於儲存和管理在網路通訊中形成的半連線狀態。
 3 
 4 背景:
 5 在TCP協議中,建立連線的過程包括三次握手。當客戶端傳送SYN包到伺服器,伺服器響應ACK包並等待客戶端的確認時,這種狀態被稱為半連線狀態。
 6 在高併發的網路環境中,如果短時間內有大量客戶端發起連線請求,伺服器可能會因為處理不過來這些半連線狀態而導致資源耗盡,進而影響服務效能。
 7 
 8 工作原理:
 9 當客戶端請求成功被服務端接收後,服務端不會立即對該請求發出響應,而是將這些請求儲存在半連線池中。
10 只要半連線池沒有滿,客戶端的請求都會進入服務端。如果半連線池已滿,新的請求將被阻攔並顯示等待。
11 半連線池透過服務端響應最早進入的客戶端請求,達到管理半連線狀態、防止資源耗盡的目的。
12 
13 作用:
14 限制同一時間內的客戶端請求數,避免伺服器因處理過多半連線狀態而資源耗盡。
15 提高伺服器在高併發環境下的穩定性和效能。
16 
17 相關概念:
18 SYN洪水攻擊:一種網路攻擊方式,透過不斷產生半連線狀態,讓伺服器無法處理正常請求。
19 連線池:一種通用的技術,用於提高資源的利用率和系統的效能。除了半連線池外,還有資料庫連線池、執行緒池等。
20 注意:
21 半連線池限制的是同一時間的客戶端請求數,而非連線數。
22 合理地配置半連線池的大小對於伺服器的效能和穩定性至關重要。

(udp協議套接字)

 1 服務端
 2 
 3 import socket
 4 
 5 server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # 資料包協議==》udp協議
 6 
 7 server.bind(('127.0.0.1', 8083))
 8 
 9 while True:
10     data, client_addr = server.recvfrom(1024)
11     server.sendto(data.upper(), client_addr)
12 
13 server.close()
14 
15 
16 -----------------------------------------------------------------------------------
17 客戶端
18 
19 import socket
20 
21 client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
22 while True:
23     msg = input('>>:').strip()
24     client.sendto(msg.encode('utf-8'), ('127.0.0.1', 8083))
25     res = client.recvfrom(1024)
26     print(res)
27 
28 client.close()

(UDP和TCP的區別)

 1 TCP與UDP都是用來規定通訊方式的
 2 區別:
 3   TCP協議稱之為流式協議、可靠協議(資料不容易丟失)
 4     面向連線
 5   UDP協議稱之為資料包協議、不可靠協議
 6     面向無連線
 7     
 8 # UDP用在哪裡?
 9 早期的QQ使用的就是純生的UDP協議
10 現在QQ自己新增了很多技術和功能
11   使用UDP的原因就是因為很簡單 快捷 粗暴 只要指定對方的地址就可以發訊息了 而TCP還要建立三握四揮
12     
13 TCP我們可以打比方為打電話 你一句我一句
14 UDP我們可以看成是發簡訊 只要發了就行 不管對方看不看

相關文章