目錄html
- 網絡分層
- TCP和UDP的區別
- TCP的三次握手和四次揮手
- TCP滑窗(好麻煩,上課的時候聽得就懵,出來混,老是要還的)
- Http協議
- Https與Http的區別
好文推薦:java
網絡分層
(OSI開放式互聯參考模型)web
七層面試
第1層 物理層
機械、 電子、定時接口通訊信道上的原始比特流傳輸算法
解釋:首先要解決兩臺物理機之間的通訊需求,機器A--->機器B發送比特流瀏覽器
(物理層主要定義了物理設備的標準,如網線的類型,光纖的接口,傳輸比特流(0/1)轉換爲電流強弱,到達目的地後,再轉換爲0/1機器碼(網卡工做在這一層))緩存
第2層 數據鏈路層
物理尋址、同時將原始比特流轉變爲邏輯傳輸線路安全
第3層 網絡層
控制子網的運行,如邏輯編址、分組傳輸、路由選擇服務器
TCP和UDP的區別
首先須要知道TCP和UDP是什麼,才能更好的理解二者之間的區別微信
TCP---傳輸控制協議
提供的是面向鏈接、可靠的基於字節流的傳輸層通訊協議。當客戶和服務器彼此交換數據前,必須先在雙方之間創建一個TCP鏈接,以後才能傳輸數據。TCP提供超時重發,丟棄重複數據,檢驗數據,流量控制等功能,保證數據能從一端傳到另外一端。
將應用層的數據流分割成報文段併發送給目標節點的TCP層
數據包都有序號,對方收到則發送ACK確認,未收到則重傳
使用校驗來檢驗數據在傳輸過程當中是否有誤
UDP---用戶數據報協議
是一個簡單的面向數據報的運輸層協議。UDP不提供可靠性,它只是把應用程序傳給IP層的數據報發送出去,可是並不能保證它們能到達目的地。因爲UDP在傳輸數據報前不用在客戶和服務器之間創建一個鏈接,且沒有超時重發等機制,故而傳輸速度很快。
特色:
- 面向非鏈接
- 不維護鏈接狀態支持同時向多個用戶傳輸相同的信息
- 數據包報頭至於8個字節,額外開銷較小
- 吞吐量只受限於數據生成速率、傳輸速率以及機器性能
- 盡最大可能交付,不保證可靠交付,不須要維持複雜的連接狀態表
- 面向報文,不對應用程序提交報文信息進行拆分或者合併
區別
- 鏈接性:TCP面向鏈接(如打電話要先撥號創建鏈接);UDP是無鏈接的,即發送數據以前不須要創建鏈接
- 可靠性:TCP提供可靠的服務。也就是說,經過TCP鏈接傳送的數據,無差錯,不丟失,不重複,且按序到達;UDP盡最大努力交付,即不保證可靠交付。Tcp經過校驗和,重傳控制,序號標識,滑動窗口、確認應答實現可靠傳輸。如丟包時的重發控制,還能夠對次序亂掉的分包進行順序控制。
- 實時性:UDP具備較好的實時性,工做效率比TCP高,適用於對高速傳輸和實時性有較高的通訊或廣播通訊。
- 傳輸方式:每一條TCP鏈接只能是點到點的;UDP支持一對一,一對多,多對一和多對多的交互通訊
- 資源:TCP對系統資源要求較多,UDP對系統資源要求較少。
應用場景
普通的會議視頻圖像,固然首選UDP,畢竟丟幾包無所謂。
傳輸文件等,不能丟包,用TCP
TCP三次握手和四次揮手
Tcp三次握手
確認序號標誌ACK:當ACK=1時,確認字段纔有效。當ACK=0時,確認號無效。TCP規定,在鏈接創建後全部傳送的報文段都必須把ACK置1。
同步序號SYN:在鏈接創建時用來同步序號。當SYN=1而ACK=0時,代表這是一個鏈接請求報文段。對方若贊成創建鏈接,則應在響應的報文段中使SYN=1和ACK=1。故SYN置爲1,就表示這是一個鏈接請求和鏈接接收報文。
序列號seq:當發送一個數據時,數據是被拆成多個數據包來發送,序列號就是對每一個數據包進行編號,這樣接受方纔能對數據包進行再次拼接。
下一個數據包的編號ack:這也就是爲何第二請求時,ack是seq+1
FIN:finish標誌,用於釋放鏈接
整個流程爲:
- 創建鏈接時,,客戶端發送SYN包(syn=j),而後進入SYN_SEND狀態,等待服務器確認(確認客戶端具備發送功能)
- 服務器收到SYN包,必須確認客戶的SYN(ackj+1),同時本身也發送一個SYN包(syn=k),即SYN+ACK包,進入SYN_RECV狀態,這個狀態被稱爲半鏈接狀態(確認服務端具備接收和發送功能)
- 客戶端再進行一次確認,收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=k+1),此包發送完畢,客戶端和服務器進入ESTABLISHED狀態(確認客戶端具備接收功能)
注意:面試時解釋儘可能不要用白話(A:喂,你聽到了嗎),對專業人員,要使用專業術語!
![](http://static.javashuo.com/static/loading.gif)
通俗解釋:
- 客戶端首先要SYN=1,表示要建立鏈接,
- 服務端接收到後,要告訴客戶端:我接受到了!因此加個ACK=1,就變成了ACK=1,SYN=1
- 理論上這時就建立鏈接成功了,因此客戶端要再發一個消息給服務端確認一下,這時只須要ACK=1就好了。
爲何要進行三次握手,而不是兩次?
首次握手隱患——SYN超時
問題原由分析:
Server收到Client的SYN,回覆SYN-ACK的時候未收到ACK確認
Server不斷重試直至超時,Linux默認等待63秒才斷開鏈接,在此期間服務器可能會遭到SYN Flood的防禦措施,攻擊者就會將隊列中 SYN耗盡,讓其餘的正常鏈接沒法處理
針對SYN Flood的防禦措施
SYN隊列滿後,經過tcp_syncookies參數回發SYN Cookie
若爲正常鏈接則Client會回發SYN Cookie,直接創建鏈接
舉個例子:
假設客戶端和服務器進行TCP鏈接,而後第一次發送的TCP鏈接請求發生了阻塞。
![](http://static.javashuo.com/static/loading.gif)
因而因爲客戶端沒有收到服務器的應答報文,客戶端認爲這個TCP鏈接請求丟失了,因而從新發送了TCP鏈接請求。此次沒有阻塞,成功鏈接了,由於是討論的兩次握手,因此只進行兩次鏈接就能夠進行通訊了。
![](http://static.javashuo.com/static/loading.gif)
通訊結束,而後就斷開了鏈接。
![](http://static.javashuo.com/static/loading.gif)
這時候最開始的阻塞的鏈接請求A客戶端覺得丟失了,可是沒有丟失,只是阻塞了而已,阻塞一段時間網絡又暢通了,因而TCP鏈接請求A成功到達了服務器,服務器又覺得是客戶端又要進行數據傳輸,因而服務器就又對這個鏈接請求進行應答,兩次握手,因而又成功創建了TCP鏈接。
![](http://static.javashuo.com/static/loading.gif)
可是因爲客戶端它覺得這個鏈接請求已經丟失了,因此不會利用這個創建的鏈接請求進行數據通訊,雖然服務器分配給了資源給客戶端,可是客戶端並不進行數據傳輸,服務端就等待客戶端的響應,這樣就白白浪費了服務器的資源,試想一下若是網絡很擁堵,那麼等網絡變暢通之後,服務器豈不是浪費了一堆資源,可能對於正常的鏈接請求都沒法處理了!
三次握手就能夠避免資源浪費,只要客戶端不迴應服務端
![](http://static.javashuo.com/static/loading.gif)
服務器過了很長時間(規定好的時間和客戶端)都沒有收到回覆,因而也不會爲客戶端分配資源,此次鏈接就放棄了。
小結:
- 兩次握手,是由於服務器收到了客戶端的消息,服務器知道了客戶端是能夠發送消息的,但因爲沒有第三次握手,因此服務器不知道客戶端是否具備接受消息的能力;
- 客戶端從服務器接受到了消息,客戶端知道了服務器接受到了個人消息纔回復,說明服務器的接受消息能力和發送消息的能力沒問題(服務器發送出了消息);
- 綜上所述,客戶端確保了服務器的接受發送沒問題,可是服務器僅僅只知道客戶端的發送消息沒問題,這並非可靠的,因此兩次握手不能夠。
總結:
三次握手確保服務端和客戶端都具備發送和接收消息能力,這樣就能夠進行通話了(創建了TCP鏈接)
TCP四次揮手
Tcp三次握手是TCP創建鏈接的過程,Tcp四次揮手則是TCP鏈接釋放的過程。
![](http://static.javashuo.com/static/loading.gif)
當客戶端沒有數據再須要發送給服務端時,就須要釋放客戶端的鏈接,這整個過程爲:
- 客戶端發送一個報文給服務端(沒有數據),其中FIN設置爲1,用來關閉Client到Server的數據傳送,客戶端進入FIN_WAIT_1狀態(客戶端Client發送FIN,用來關閉Client到Server的數據傳送)
- 服務端收到來自客戶端的FIN,發送一個ACK給客戶端,確認序號爲收到序號+1 ,(與SYN相同,一個FIN佔用一個序號),服務端進入CLOSE_WAIT狀態(此時TCP連接處於半關閉狀態,即客戶端已經沒有要發送的數據了,但服務端若發送數據,則客戶端仍要接收。)
- 服務端發送一個FIN給客戶端,用來關閉服務端到客戶端的數據傳送,服務端進入LAST_ACK狀態(服務端Server發送一個FIN,用來關閉Server到Client的數據傳送)
- 客戶端收到FIN後,進入TIME_WAIT狀態,接着發送一個ACK給服務端,確認序號爲收到序號+1,最後客戶端和服務端都進入CLOSED狀態
爲何會有TIME_WAIT狀態,不直接轉換爲CLOSED ?
- 確認有足夠的時間讓對方收到ACK包(若是被動關閉的那端沒有收到ACK包,就會觸發被動端重發FIN包 ,一來一去就是2MSL)
- 避免新舊鏈接混淆(由於有些路由器會緩存IP數據包,若是鏈接被重用了,就可能會跟新鏈接混在一塊兒)
爲何須要四次握手才能斷開鏈接?
- 由於全雙工,發送方和接收方都須要FIN報文和ACK報文
服務器出現大量CLOSE_WAIT狀態的緣由
出現大量CLOSE_WAIT,只可能值客戶端發送了FIN,服務端沒有進一步發送ACK,或者FIN已經確認
對方關閉socket鏈接,我方忙於讀寫,沒有及時關閉鏈接
- 檢查代碼,特別是釋放資源的代碼
- 檢查配置,特別是處理請求的線程配置
TCP的滑動窗口
TCP的滑動窗口作流量控制與亂序重排
保證TCP的可靠性
保證TCP的流控特性
RTT和RTO
RTT:發送一個數據包到收到對應的ACK,所花費的時間
RTO:重傳時間間隔
TCP使用滑動窗口作瀏覽控制
Http協議
特色
請求/響應的步驟:
- 客戶端鏈接到Web服務器
- 發送HTTP請求
- 服務器接收請求並返回HTTO響應
- 釋放鏈接TCP鏈接
- 客戶端瀏覽器解析HTML內容
以前歷來沒注意到的一個點,忽然想起以前某人說的,面試中遇到的一個問題:地址欄中輸入URL會發生什麼?
在這整個過程當中,大體能夠分爲如下幾個過程
- DNS域名解析:瀏覽器自己是一個客戶端,當你輸入URL的時候,首先瀏覽器會去請求DNS服務器(從近及遠,瀏覽器緩存、路由器緩存、IPS服務器緩存、域名服務器緩存,頂級域名服務器,還有一個緩存沒聽清),經過DNS獲取相應的域名對應的IP
- TCP鏈接:而後經過IP地址找到IP對應的服務器後,要求創建TCP鏈接
- HTTP請求:瀏覽器發送完HTTP Request(請求)包後,服務器接收到請求包以後纔開始處理請求包
- 服務器處理請求返回HTTP響應:在服務器收到請求以後,服務器調用自身服務,返回HTTP Response(響應)包
- 瀏覽器頁面渲染:客戶端收到來自服務器的響應後開始渲染這個Response包裏的主體(body)
- 關閉鏈接:等收到所有的內容隨後斷開與該服務器之間的TCP鏈接。
![](http://static.javashuo.com/static/loading.gif)
當咱們在瀏覽器地址欄上輸入要訪問的URL後,瀏覽器會分析出URL上面的域名,而後經過DNS服務器查詢出域名映射的IP地址,瀏覽器根據查詢到的IP地址與Web服務器進行通訊,而通訊的協議就是HTTP協議。
HTTP狀態碼
- 1xx:指示信息——表示請求已接受,繼續處理
- 2xx:成功——表示請求已被成功接收、理解、接受
- 3xx:重定向——要完成請求必須進行更進一步的操做
- 4xx:客戶端錯誤——請求有語法錯誤或者請求沒法實現
- 5xx:服務器端錯誤——服務器未能實現合法的請求
常見的狀態碼
- 200 OK:客戶端請求成功
- 301 Moved Permanently(永久移除):請求的URL已經移走。Response中應該包含一個Location URL,說明資源如今所處的位置
- 302 found:重定向
- 400 Bad Request:客戶端請求有語法錯誤,不能被服務器所理解
- 401 Unaythorized:請求未經受權,這個狀態碼必須和WWW-Authenticate報頭域一塊兒使用
- 403 Forbidden:服務端禁止訪問該資源
- 404 Not Found:請求資源不存在,輸入了錯誤的URL
- 500 Internal Server Error:服務器發生了不可預期的錯誤
- 503 Server Unavaliable:服務器當前不能處理客戶端的請求,一段時間後可能恢復正常
HTTP中重定向和轉發的區別
本質區別:轉發是服務器行爲,重定向是客戶端行爲
重定向:兩次請求,瀏覽器地址發生變化,可訪問自身web以外的資源,傳輸的數據會丟失
請求轉發:一次請求,地址不變,訪問自身web資源,傳輸的數據不會丟失
GET請求和POST請求的區別
- GET將請求信息放在URL,POST放在報文體
- GET請求的數據會附在URL以後,以?分割URL和傳輸數據,參數之間以&相連
- POST請求把提交的數據放放再HTTP包的包體中
- GET提交的數據最多隻能是1024字節,理論上POST沒有限制
- POST的安全性要比GET高
- 經過GET提交數據,那麼用戶名和密碼將出如今URL上,登陸頁面也能被瀏覽器緩存,其餘人查看瀏覽器的歷史記錄就可能拿到用戶名和密碼,除此以外,使用GET提交數據可能會形成Cross-site request forgery攻擊
GET和POST兩種基本請求方法的區別
Cookie和Session的區別
Cookie
- 是由服務器發送給客戶端的特殊信息,以文本的形式存放在客戶端
- 客戶端再次請求時,會把Cookie回發
- 服務器接收到後, 會解析Cookie生成與客戶端相對應的內容
Cookie的設置以及發送過程
![](http://static.javashuo.com/static/loading.gif)
Session
- 服務器端的機制,在服務器上保存的信息
- 解析客戶端請求並操做session id,按需保存狀態信息
Session的實現方式
- 使用Cookie來實現
![](http://static.javashuo.com/static/loading.gif)
2.使用URL回寫來實現
服務器發送給瀏覽器全部頁面都攜帶SessionId的參數,客戶端點擊任何一個鏈接,都會使SessionId帶回給服務器,......
HTTP協議是構建在TCP/IP協議之上的,是TCP/IP協議的一個子集,因此要理解HTTP協議,有必要先了解下TCP/IP協議相關的知識。
不一樣點:
- 不管客戶端怎麼設置,session都能正常工做,當客戶端僅用cookie時將沒法使用cookie
- session可存儲任意的java對象,cookie只能存儲String類型的對象
TCP/IP的分層管理
TCP/IP協議族包含了不少協議,按層次分有四層:應用層、傳輸層、網絡層、數據鏈路層。
- 應用層:包含了各類通用的應用服務,好比 FTP(File Transfer Protocol,文件傳輸協議)、DNS、HTTP等。
- 傳輸層:提供網絡中兩臺計算機之間的數據傳輸,好比TCP、UDP。
- 網絡層:處理在網絡上流動的數據包,該層規定了傳輸路線,數據包經過怎樣的路徑傳送到對方的計算機中。好比 IP。
- 數據鏈路層:鏈接網絡的硬件部分,包括網卡,光纖等等硬件設備
TCP/IP模型與OSI模型對比
![](http://static.javashuo.com/static/loading.gif)
HTTP、TCP/IP、DNS之間的關係
當客戶端訪問Web站點時,首先會經過DNS服務查詢到域名的IP地址。而後瀏覽器生成HTTP請求,並經過TCP/IP協議發送給Web服務器。Web服務器接收到請求後會根據請求生成響應內容,並經過TCP/IP協議返回給客戶端。
Https與Http的區別
Http協議運行在TCP之上,用來在 Internet 上傳送超文本的傳送協議,它可使瀏覽器更加高效,使網絡傳輸減小。但 HTTP 協議採用明文傳輸信息,客戶端與服務器端都沒法驗證對方的身份,存在信息竊聽、信息篡改和信息劫持的風險。;
Https是身披SSL(Secure Socket Layer)外殼的Http,運行於SSL上,SSL運行於TCP之上,是添加了加密和認證機制的HTTP。兩者之間存在以下不一樣:
- 端口不一樣:Http與Https使用不一樣的鏈接方式,。用的端口也不同,前者是80,後者是443
- 資源消耗:和Http通訊相比,Https通訊會因爲加減密處理消耗更多的CPU和內存資源;
- 開銷:Https通訊須要到CA機構申請SSL證書,而證書通常須要向認證機構購買;
- 安全性:Http無狀態傳輸,HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網絡協議(HTTPS=HTTP+加密+認證+完整性保護),要比Http協議安全。
- 傳輸方式:Http明文傳輸,Https是密文傳輸
![](http://static.javashuo.com/static/loading.gif)
加密方式
這種方式存在的最大問題就是密鑰發送問題,即如何安全地將密鑰發給對方;
- 非對稱加密:指使用一對非對稱密鑰,即公鑰和私鑰,公鑰能夠隨意發佈,但私鑰只有本身知道。
發送密文的一方使用對方的公鑰進行加密處理,對方接收到加密信息後,使用本身的私鑰進行解密。
因爲非對稱加密的方式不須要發送用來解密的私鑰,因此能夠保證安全性;可是和對稱加密比起來,它很是的慢,因此咱們仍是要用對稱加密來傳送消息,但對稱加密所使用的密鑰咱們能夠經過非對稱加密的方式發送出去。
- 哈希算法:將任意長度的信息轉換爲固定的長度的值,算法不可逆
- 數字簽名:證實某個消息或者文件時某人發出/認同的
Https的加密機制是一種共享密鑰加密和公開密鑰加密並用的混合加密機制。
HTTPS數據傳輸流程
- 瀏覽器將支持的加密算法信息發送給服務器
- 服務器選擇一套瀏覽器支持的加密算法,以證書的形式回發瀏覽器
- 瀏覽器驗證證書合法性,並結合證書公鑰加密信息發送給服務器
- 服務器使用私鑰解密信息,驗證哈希,加密響應消息回發瀏覽器
- 瀏覽器解密響應消息,並對消息進行驗證,以後進行加密交互數據
Https真的很安全嘛?
不必定
- 瀏覽器默認填充http://,https->http請求須要進行跳轉,有被劫持的風險
- 可使用HSTS(HTTP Strict Transport Security)優化
Socket簡介
兩個進程須要進行通訊,最基本的前提可以惟一的標識一個進程
在本地進程通訊中,使用pid來標識一個進程,可是pid只在本地惟一,網絡中兩個進程的pid的衝突可能性是比較高的
因此須要另闢蹊徑,ip層的ip地址能夠惟一標識一臺主機,而TCP協議和端口號能夠惟一標識主機的一個進程
——>>能夠利用IP地址+TCP協議+端口號來惟一標識網絡的一個進程,就可使用socket進行通訊
Scoket是TCP/IP協議的抽象(socket的出現只是爲了更好的使用TCP/IP協議),是操做系統對外開放的接口
![](http://static.javashuo.com/static/loading.gif)
Socket的通訊流程
![](http://static.javashuo.com/static/loading.gif)
socket相關面試題
編寫一個網絡應用程序,有客戶端和服務器端,客戶端向服務器發送一個字符串,服務器收到該字符串後將其打印到命令行上,而後向客戶端返回該字符串的長度,最後,客戶端輸出服務器端返回該字符串的長度,分別用TCP和UDP兩種方式實現
本文轉發整合: