【傳輸層協議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我們可以看成是發簡訊 只要發了就行 不管對方看不看