網(wǎng)絡通信過程:
- MAC地址:在設備與設備之間數(shù)據(jù)通信時用來標記收發(fā)雙方(網(wǎng)卡的序列號)
- IP地址:在邏輯上標記一臺電腦拌牲,用來指引數(shù)據(jù)包的收發(fā)方向(相當于電腦的序列號)
- 網(wǎng)絡掩碼:用來區(qū)分ip地址的網(wǎng)絡號和主機號
- 默認網(wǎng)關:當需要發(fā)送的數(shù)據(jù)報包的目的ip不在本網(wǎng)段內(nèi)時,就會發(fā)送給默認的一臺電腦,稱為網(wǎng)關
- 集線器:已過時败去,用來連接多臺電腦,缺點:每次收發(fā)數(shù)據(jù)都進行廣播(數(shù)據(jù)安全)蝗岖,網(wǎng)絡會變的擁堵
- 交換機:集線器的升級版赤拒,有學習功能知道需要發(fā)送給哪臺設備,根據(jù)需要進行單播莫杈、廣播(ARP協(xié)議包(地址解析協(xié)議)-->根據(jù)ip地址獲取對應的MAC地址)
- 路由器:連接多個不同互例,的網(wǎng)段,讓他們之間可以進行收發(fā)數(shù)據(jù)筝闹,每次收到數(shù)據(jù)后媳叨,ip不變,但是MAC地址會變化
- DHCP:動態(tài)主機分配IP地址关顷,自動給網(wǎng)絡中的主機分配IP地址
- DNS:根據(jù)域名用來解析出IP(類似電話簿)
- http服務器:提供瀏覽器能夠訪問到的數(shù)據(jù)
- NAT:網(wǎng)絡地址轉(zhuǎn)換器糊秆,將局域網(wǎng)地址和公網(wǎng)地址進行映射
HTTP協(xié)議:
- 超文本傳輸協(xié)議(HyperText Transfer Protocol)是一種應用層協(xié)議
- HTTP是萬維網(wǎng)的數(shù)據(jù)通信的基礎
- HTML超文本標記語言,是一種用來定義網(wǎng)頁的文本
- 作用:實現(xiàn)HTML網(wǎng)頁相關資源的傳送
- Elements顯示網(wǎng)頁的結(jié)構(gòu)
- Network顯示瀏覽器和服務器的通信
瀏覽器請求和服務器相應
GET表示一個讀取請求
失敗的相應有404 Not Found:網(wǎng)頁不存在
500 Internal Server Error:服務器內(nèi)部出錯
Content-Type提示相應的內(nèi)容
HTTP請求步驟
步驟1:瀏覽器首先向服務器發(fā)送HTTP請求议双,請求包括:
方法:GET還是POST痘番,GET僅請求資源,POST會附帶用戶數(shù)據(jù)平痰;
路徑:/full/url/path;
域名:由Host頭指定:Host:www.sina.com 以及其他相關的Header;
步驟2:服務器向瀏覽器返回HTTP相應汞舱,相應包括:
相應代碼:200表示成功(OK),3xx表示重定向宗雇,4xx表示客戶端發(fā)送的請求有錯誤(比如404 Not Found), 5xx表示服務器端處理時發(fā)生了錯誤(比如 503 Service Unavailable);
響應類型:由Content-Type指定昂芜,以及其他相關的Header;
步驟3:如果瀏覽器還需要繼續(xù)向服務器請求其他資源,比如圖片赔蒲,就再次發(fā)出HTTP請求泌神,重復1、2
HTTP格式
- 每個HTTP請求和響應都遵循相同的格式嘹履,一個HTTP包含Header和Body兩部分,其中Body是可選的
HTTP GET請求的格式:
GET /path HTTP/1.1
Header1:Value1
Header2:Value2
Header3:Value3
每個Hearer一行一個腻扇,換行符是\r\n
HTTP POST請求的格式:
POST /path HTTP/1.1
Header1:Value1
Header2:Value2
Header3:Value3
body data goes here...
每一行換行符是\r\n
當遇到連續(xù)兩個\r\n時,Header部分結(jié)束,后面的數(shù)據(jù)全部是Body
HTTP響應的格式:
200 OK HTTP/1.1
Header1: Value1
Header2: Value2
Header3: value3
body data goes here...
沒一行換行符是\r\n
HTTP響應如果包含body,也是通過\r\n\r\n來分隔的
請注意:Bodyde 數(shù)據(jù)類型由Content-Type頭來確定砾嫉;當存在Content-Encoding時幼苛,Body數(shù)據(jù)是被壓縮的(壓縮的目的在于減少Body的大小,加快網(wǎng)絡傳輸)
請求報文格式
請求行[方法 路徑 版本\r\n]
請求頭[頭名稱:頭值\r\n]
空行[\r\n]
請求體
響應報文格式
響應行[版本 響應狀態(tài)]
響應頭[頭名稱:頭值]
空行
響應體
長連接和短連接:
- TCP在真正的讀寫操作之前焕刮,server與client之間必須建立一個連接舶沿,當讀寫操作完成后墙杯,雙方不再需要這個連接時它們可以釋放這個連接,連接的建立通過三次握手括荡,釋放則需要四次握手高镐,所以說每個連接的建立都是需要資源消耗和時間消耗的
TCP短鏈接(模擬一種情況)
- 1.client 向 server 發(fā)起連接請求
- 2.server 接到請求,雙方建立連接
- 3.client 向 server 發(fā)送消息
- 4.server 回應 client
- 5.一次讀寫完成畸冲,此時雙方任何一個都可以發(fā)起 close 操作
TCP長連接(模擬一種情況)
- 1.client 向 server 發(fā)起連接
- 2.server 接到請求嫉髓,雙方建立連接
- 3.client 向 server 發(fā)送消息
- 4.server 回應 client
- 5.一次讀寫完成,連接不關閉
- 6.后續(xù)讀寫操作..
- 7.長時間操作之后client發(fā)起關閉請求
TCP長/短連接操作過程
# 短連接的操作步驟:
建立連接——數(shù)據(jù)傳輸——關閉連接...建立連接——數(shù)據(jù)傳輸——關閉連接
# 長連接的操作步驟:
建立連接——數(shù)據(jù)傳輸...(保持連接)...數(shù)據(jù)傳輸——關閉連接
TCP長/短連接的優(yōu)點個缺點
長連接可以省去較多的TCP建立和關閉的操作邑闲,減少浪費算行,節(jié)約時間。對于頻繁請求資源的客戶來說苫耸,較適用長連接州邢。
client與server之間的連接如果一直不關閉的話,會存在一個問題褪子,隨著客戶端連接越來越多量淌,server早晚有扛不住的時候,這時候server端需要采取一些策略嫌褪,如關閉一些長時間沒讀寫事件發(fā)生的連接呀枢,這樣可以避免一些惡意連接導致server端服務受損;如果條件再允許就可以以客戶端機器為顆粒度渔扎,限制每個客戶端的最大長連接數(shù)硫狞,這樣可以完全避免某個蛋疼的客戶端連累后端服務信轿。
短連接對于服務器來說管理較為簡單晃痴,存在的連接都是有用的連接,不需要額外的控制手段财忽。
但如果客戶請求頻繁倘核,將在TCP的建立和關閉操作上浪費時間和帶寬。
TCP長/短連接的應用場景
長連接多用于操作頻繁即彪,點對點的通訊紧唱,而且連接數(shù)不能太多情況.每個TCP連接都需要三次握手,這需要時間隶校,如果每個操作都是先連接漏益,再操作的話那么處理速度會降低很多,所以每個操作完后都不斷開深胳,再次處理時直接發(fā)送數(shù)據(jù)包就OK了绰疤,不用建立TCP連接。
小的WEB網(wǎng)站的http服務一般都用短鏈接舞终,因為長連接對于服務端來說會耗費一定的資源轻庆,而像WEB網(wǎng)站這么頻繁的成千上萬甚至上億客戶端的連接用短連接會更省一些資源癣猾,如果用長連接,同時有成千上萬的用戶余爆,如果每個用戶都占用一個連接的話纷宇,那可想而知吧。所以并發(fā)量大蛾方,但每個用戶無需頻繁操作情況下需用短連好像捶。
對于中大型WEB網(wǎng)站一般都采用長連接,好處是響應用戶時間更短桩砰,用戶體驗更好作岖,雖然更耗硬件資源一些,但這都不是事兒五芝。
小案例(模擬瀏覽器)
import socket
# 創(chuàng)建TCP連接
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# DNS解析 和 連接HTTP服務器
tcp_socket.connect(("www.itcastcpp.cn", 80))
# 組包 發(fā)送HTTP請求報文
# 請求行
request_line = "GET / HTTP/1.1\r\n"
# 請求頭
request_header = "Host: www.itcastcpp.cn\r\n"
request_data = request_line + request_header + "\r\n"
# 發(fā)送請求
tcp_socket.send(request_data.encode())
# 接收響應報文
response_data = tcp_socket.recv(4096)
# 對響應報文進行解析 -- 切割
response_str_data = response_data.decode()
# print(response_data)
# '\r\n\r\n'之后的數(shù)據(jù)就是響應體數(shù)據(jù)
index = response_str_data.find("\r\n\r\n")
# 切割出的數(shù)據(jù)就是文件數(shù)據(jù)
html_data = response_str_data[index+4:]
# data_file = open("index.html", "wb")
# data_file.write(html_data.encode())
# data_file.close()
with open("index.html", "wb") as file:
file.write(html_data.encode())
# 關閉套接字
tcp_socket.close()