## 先看一天面試的經驗:
**第一場:**
* 面試官:你說一下TCP的三次握手
* 我:第一次Client將SYN置1......、第二次Server收........、 第三次........
* 面試官:很難背吧?
* 我:......是啊,很難,要不我在和你說說四次揮手?
* 面試官:別了別了回去等通知吧......
* 我:"......"
**第二場:** `心里憋了一萬個草泥馬來到的第二家`
* ....
* 面試官:你說一下TCP的三次握手
* 我(`心里在想,還來?`):沒什么好說的,就是為了保持一次網絡通信交互正常
* 面試官:你能說的清楚一點嗎?
* 我:就等于是你在不認識我的情況下打我的電話讓我來面試
* 面試官:“懵了”,好像是這么回事
* 面試官:你說一下TCP的四次揮手
* 我:等于是我在上家公司辭職了
* 面試官:“想了一下”,能不能說的清楚一點嗎?
* 我:我找老板辦理離職,老板說可以,老板接著給我辦理離職,我才可以走
* 面試官:有道理!
* 面試官:你說一下TCP和UDP的區別吧
* 我:TCP等于和陌生人打電話處理事情,UDP等于發廣播
* 面試官:“...”有道理
* 面試官:你期望薪資多少
* 我:15K
* 面試官:下周一有時間入職?
* 我:....
`接著進入正題`
## 什么是網絡編程
* 網絡編程的本質是多臺計算機之間的數據交換。數據傳遞本身沒有多大的難度,不就是把一個設備中的數據發送給其他設備,然后接受另外一個設備反饋的數據。現在的網絡編程基本上都是基于請求/響應方式的,也就是一個設備發送請求數據給另外一個,然后接收另一個設備的反饋。在網絡編程中,發起連接程序,也就是發送第一次請求的程序,被稱作客戶端(Client),等待其他程序連接的程序被稱作服務器(Server)。客戶端程序可以在需要的時候啟動,而服務器為了能夠時刻相應連接,則需要一直啟動。
* 例如以打電話為例,首先撥號的人類似于客戶端,接聽電話的人必須保持電話暢通類似于服務器。連接一旦建立以后,就客戶端和服務器端就可以進行數據傳遞了,而且兩者的身份是等價的。在一些程序中,程序既有客戶端功能也有服務器端功能,最常見的軟件就是QQ、微信這類軟件了。
## 網絡編程中兩個主要的問題
1. 一個是如何準確的定位網絡上一臺或多臺主機,
2. 另一個就是找到主機后如何可靠高效的進行數據傳輸。
* 在TCP/IP協議中IP層主要負責網絡主機的定位,數據傳輸的路由,由IP地址可以唯一地確定Internet上的一臺主機。
* 而TCP層則提供面向應用的可靠(TCP)的或非可靠(UDP)的數據傳輸機制,這是網絡編程的主要對象,一般不需要關心IP層是如何處理數據的。
* 目前較為流行的網絡編程模型是客戶機/服務器(C/S)結構。即通信雙方一方作為服務器等待客戶提出請求并予以響應。客戶則在需要服務時向服務器提 出申請。服務器一般作為守護進程始終運行,監聽網絡端口,一旦有客戶請求,就會啟動一個服務進程來響應該客戶,同時自己繼續監聽服務端口,使后來的客戶也 能及時得到服務。
## 網絡協議是什么
* 在計算機網絡要做到井井有條的交換數據,就必須遵守一些事先約定好的規則,比如交換數據的格式、是否需要發送一個應答信息。這些規則被稱為網絡協議。
## 為什么要對網絡協議分層
* 簡化問題難度和復雜度。由于各層之間獨立,我們可以分割大問題為小問題。
* 靈活性好。當其中一層的技術變化時,只要層間接口關系保持不變,其他層不受影響。
* 易于實現和維護。
* 促進標準化工作。分開后,每層功能可以相對簡單地被描述
## 計算機網絡體系結構

* **OSI參考模型**
* OSI(Open System Interconnect),即開放式系統互聯。一般都叫OSI參考模型,是ISO(國際標準化組織)組織在1985年研究的網絡互連模型。ISO為了更好的使網絡應用更為普及,推出了OSI參考模型,這樣所有的公司都按照統一的標準來指定自己的網絡,就可以互通互聯了。
* OSI定義了網絡互連的七層框架(物理層、數據鏈路層、網絡層、傳輸層、會話層、表示層、應用層)。
> 
* **TCP/IP參考模型**
* TCP/IP四層協議(數據鏈路層、網絡層、傳輸層、應用層)
1. 應用層 應用層最靠近用戶的一層,是為計算機用戶提供應用接口,也為用戶直接提供各種網絡服務。我們常見應用層的網絡服務協議有:HTTP,HTTPS,FTP,TELNET等。
2. 傳輸層 建立了主機端到端的鏈接,傳輸層的作用是為上層協議提供端到端的可靠和透明的數據傳輸服務,包括處理差錯控制和流量控制等問題。該層向高層屏蔽了下層數據通信的細節,使高層用戶看到的只是在兩個傳輸實體間的一條主機到主機的、可由用戶控制和設定的、可靠的數據通路。我們通常說的,TCP UDP就是在這一層。端口號既是這里的“端”。
3. 網絡層 本層通過IP尋址來建立兩個節點之間的連接,為源端的運輸層送來的分組,選擇合適的路由和交換節點,正確無誤地按照地址傳送給目的端的運輸層。就是通常說的IP層。這一層就是我們經常說的IP協議層。IP協議是Internet的基礎。
4. 數據鏈路層 通過一些規程或協議來控制這些數據的傳輸,以保證被傳輸數據的正確性。實現這些規程或協議的`硬件`和軟件加到物理線路,這樣就構成了數據鏈路,
### 1 TCP / UDP
#### 1.1 什么是TCP/IP和UDP
* TCP/IP即傳輸控制/網絡協議,是面向連接的協議,發送數據前要先建立連接(發送方和接收方的成對的兩個之間必須建 立連接),TCP提供可靠的服務,也就是說,通過TCP連接傳輸的數據不會丟失,沒有重復,并且按順序到達
* UDP它是屬于TCP/IP協議族中的一種。是無連接的協議,發送數據前不需要建立連接,是沒有可靠性的協議。因為不需要建立連接所以可以在在網絡上以任何可能的路徑傳輸,因此能否到達目的地,到達目的地的時間以及內容的正確性都是不能被保證的。
#### 1.2 TCP與UDP區別:
* TCP是面向連接的協議,發送數據前要先建立連接,TCP提供可靠的服務,也就是說,通過TCP連接傳輸的數據不會丟失,沒有重復,并且按順序到達;
* UDP是無連接的協議,發送數據前不需要建立連接,是沒有可靠性;
* TCP通信類似于于要打個電話,接通了,確認身份后,才開始進行通行;
* UDP通信類似于學校廣播,靠著廣播播報直接進行通信。
* TCP只支持點對點通信,UDP支持一對一、一對多、多對一、多對多;
* TCP是面向字節流的,UDP是面向報文的; 面向字節流是指發送數據時以字節為單位,一個數據包可以拆分成若干組進行發送,而UDP一個報文只能一次發完。
* TCP首部開銷(20字節)比UDP首部開銷(8字節)要大
* UDP 的主機不需要維持復雜的連接狀態表
#### 1.3 TCP和UDP的應用場景:
* 對某些實時性要求比較高的情況使用UDP,比如游戲,媒體通信,實時直播,即使出現傳輸錯誤也可以容忍;其它大部分情況下,HTTP都是用TCP,因為要求傳輸的內容可靠,不出現丟失的情況
#### 1.4 形容一下TCP和UDP
* **TCP通信可看作打電話:**
李三(撥了個號碼):喂,是王五嗎? 王五:哎,您誰啊? 李三:我是李三,我想給你說點事兒,你現在方便嗎? 王五:哦,我現在方便,你說吧。 甲:那我說了啊? 乙:你說吧。 (連接建立了,接下來就是說正事了…)
* **UDP通信可看為學校里的廣播:**
播音室:喂喂喂!全體操場集合
#### 1.5 運行在TCP 或UDP的應用層協議分析。
* 運行在TCP協議上的協議:
* HTTP(Hypertext Transfer Protocol,超文本傳輸協議),主要用于普通瀏覽。
* HTTPS(HTTP over SSL,安全超文本傳輸協議),HTTP協議的安全版本。
* FTP(File Transfer Protocol,文件傳輸協議),用于文件傳輸。
* POP3(Post Office Protocol, version 3,郵局協議),收郵件用。
* SMTP(Simple Mail Transfer Protocol,簡單郵件傳輸協議),用來發送電子郵件。
* TELNET(Teletype over the Network,網絡電傳),通過一個終端(terminal)登陸到網絡。
* SSH(Secure Shell,用于替代安全性差的TELNET),用于加密安全登陸用。
* 運行在UDP協議上的協議:
* BOOTP(Boot Protocol,啟動協議),應用于無盤設備。
* NTP(Network Time Protocol,網絡時間協議),用于網絡同步。
* DHCP(Dynamic Host Configuration Protocol,動態主機配置協議),動態配置IP地址。
* 運行在TCP和UDP協議上:
* DNS(Domain Name Service,域名服務),用于完成地址查找,郵件轉發等工作。
* ECHO(Echo Protocol,回繞協議),用于查錯及測量應答時間(運行在[TCP](https://link.juejin.cn?target=http%3A%2F%2Fzh.wikipedia.org%2Fzh-cn%2FTCP "http://zh.wikipedia.org/zh-cn/TCP")和[UDP](https://link.juejin.cn?target=http%3A%2F%2Fzh.wikipedia.org%2Fzh-cn%2FUDP "http://zh.wikipedia.org/zh-cn/UDP")協議上)。
* SNMP(Simple Network Management Protocol,簡單網絡管理協議),用于網絡信息的收集和網絡管理。
* DHCP(Dynamic Host Configuration Protocol,動態主機配置協議),動態配置IP地址。
* ARP(Address Resolution Protocol,地址解析協議),用于動態解析以太網硬件的地址。
#### 什么是ARP協議 (Address Resolution Protocol)?
* **ARP協議完成了IP地址與物理地址的映射**。每一個主機都設有一個 ARP 高速緩存,里面有**所在的局域網**上的各主機和路由器的 IP 地址到硬件地址的映射表。當源主機要發送數據包到目的主機時,會先檢查自己的ARP高速緩存中有沒有目的主機的MAC地址,如果有,就直接將數據包發到這個MAC地址,如果沒有,就向**所在的局域網**發起一個ARP請求的廣播包(在發送自己的 ARP 請求時,同時會帶上自己的 IP 地址到硬件地址的映射),收到請求的主機檢查自己的IP地址和目的主機的IP地址是否一致,如果一致,則先保存源主機的映射到自己的ARP緩存,然后給源主機發送一個ARP響應數據包。源主機收到響應數據包之后,先添加目的主機的IP地址與MAC地址的映射,再進行數據傳送。如果源主機一直沒有收到響應,表示ARP查詢失敗。
* 如果所要找的主機和源主機不在同一個局域網上,那么就要通過 ARP 找到一個位于本局域網上的某個路由器的硬件地址,然后把分組發送給這個路由器,讓這個路由器把分組轉發給下一個網絡。剩下的工作就由下一個網絡來做。
#### 什么是NAT (Network Address Translation, 網絡地址轉換)?
* 用于解決內網中的主機要和因特網上的主機通信。由NAT路由器將主機的本地IP地址轉換為全球IP地址,分為靜態轉換(轉換得到的全球IP地址固定不變)和動態NAT轉換。
#### 從輸入址到獲得頁面的過程?
1. 瀏覽器查詢 DNS,獲取域名對應的IP地址:具體過程包括瀏覽器搜索自身的DNS緩存、搜索操作系統的DNS緩存、讀取本地的Host文件和向本地DNS服務器進行查詢等。對于向本地DNS服務器進行查詢,如果要查詢的域名包含在本地配置區域資源中,則返回解析結果給客戶機,完成域名解析(此解析具有權威性);如果要查詢的域名不由本地DNS服務器區域解析,但該服務器已緩存了此網址映射關系,則調用這個IP地址映射,完成域名解析(此解析不具有權威性)。如果本地域名服務器并未緩存該網址映射關系,那么將根據其設置發起遞歸查詢或者迭代查詢;
2. 瀏覽器獲得域名對應的IP地址以后,瀏覽器向服務器請求建立鏈接,發起三次握手;
3. TCP/IP鏈接建立起來后,瀏覽器向服務器發送HTTP請求;
4. 服務器接收到這個請求,并根據路徑參數映射到特定的請求處理器進行處理,并將處理結果及相應的視圖返回給瀏覽器;
5. 瀏覽器解析并渲染視圖,若遇到對js文件、css文件及圖片等靜態資源的引用,則重復上述步驟并向服務器請求這些資源;
6. 瀏覽器根據其請求到的資源、數據渲染頁面,最終向用戶呈現一個完整的頁面。
#### 1.6 TCP的三次握手
##### 1.6.1 什么是TCP的三次握手
* 在網絡數據傳輸中,傳輸層協議TCP是要建立連接的可靠傳輸,TCP建立連接的過程,我們稱為三次握手。
##### 1.6.2 三次握手的具體細節

1. 第一次握手:Client將SYN置1,隨機產生一個初始序列號seq發送給Server,進入SYN\_SENT狀態;
2. 第二次握手:Server收到Client的SYN=1之后,知道客戶端請求建立連接,將自己的SYN置1,ACK置1,產生一個acknowledge number=sequence number+1,并隨機產生一個自己的初始序列號,發送給客戶端;進入SYN\_RCVD狀態;
3. 第三次握手:客戶端檢查acknowledge number是否為序列號+1,ACK是否為1,檢查正確之后將自己的ACK置為1,產生一個acknowledge number=服務器發的序列號+1,發送給服務器;進入ESTABLISHED狀態;服務器檢查ACK為1和acknowledge number為序列號+1之后,也進入ESTABLISHED狀態;完成三次握手,連接建立。
* 簡單來說就是 :
1. 客戶端向服務端發送SYN
2. 服務端返回SYN,ACK
3. 客戶端發送ACK
##### 1.6.3 用現實理解三次握手的具體細節
* 三次握手的目的是建立可靠的通信信道,主要的目的就是雙方確認自己與對方的發送與接收機能正常。
1. 第一次握手:客戶什么都不能確認;服務器確認了對方發送正常
2. 第二次握手:客戶確認了:自己發送、接收正常,對方發送、接收正常;服務器確認 了:自己接收正常,對方發送正常
3. 第三次握手:客戶確認了:自己發送、接收正常,對方發送、接收正常;服務器確認 了:自己發送、接收正常,對方發送接收正常 所以三次握手就能確認雙發收發功能都正常,缺一不可。
##### 1.6.4 建立連接可以兩次握手嗎?為什么?
* 不可以。
* 因為可能會出現已失效的連接請求報文段又傳到了服務器端。 > client 發出的第一個連接請求報文段并沒有丟失,而是在某個網絡結點長時間的滯留了,以致延誤到連接釋放以后的某個時間才到達 server。本來這是一個早已失效的報文段。但 server 收到此失效的連接請求報文段后,就誤認為是 client 再次發出的一個新的連接請求。于是就向 client 發出確認報文段,同意建立連接。假設不采用 “三次握手”,那么只要 server 發出確認,新的連接就建立了。由于現在 client 并沒有發出建立連接的請求,因此不會理睬 server 的確認,也不會向 server 發送數據。但 server 卻以為新的運輸連接已經建立,并一直等待 client 發來數據。這樣,server 的很多資源就白白浪費掉了。采用 “三次握手” 的辦法可以防止上述現象發生。例如剛才那種情況,client 不會向 server 的確認發出確認。server 由于收不到確認,就知道 client 并沒有要求建立連接。
* 而且,兩次握手無法保證Client正確接收第二次握手的報文(Server無法確認Client是否收到),也無法保證Client和Server之間成功互換初始序列號。
##### 1.6.5 可以采用四次握手嗎?為什么?
* 這個肯定可以。三次握手都可以保證連接成功了,何況是四次,但是會降低傳輸的效率。
##### 1.6.6 第三次握手中,如果客戶端的ACK未送達服務器,會怎樣?
* Server端:由于Server沒有收到ACK確認,因此會每隔 3秒 重發之前的SYN+ACK(默認重發五次,之后自動關閉連接進入CLOSED狀態),Client收到后會重新傳ACK給Server。
* Client端,會出現兩種情況:
1. 在Server進行超時重發的過程中,如果Client向服務器發送數據,數據頭部的ACK是為1的,所以服務器收到數據之后會讀取 ACK number,進入 establish 狀態
2. 在Server進入CLOSED狀態之后,如果Client向服務器發送數據,服務器會以RST包應答。
##### 1.6.7 如果已經建立了連接,但客戶端出現了故障怎么辦?
* 服務器每收到一次客戶端的請求后都會重新復位一個計時器,時間通常是設置為2小時,若兩小時還沒有收到客戶端的任何數據,服務器就會發送一個探測報文段,以后每隔75秒鐘發送一次。若一連發送10個探測報文仍然沒反應,服務器就認為客戶端出了故障,接著就關閉連接。
##### 1.6.8 初始序列號是什么?
* TCP連接的一方A,隨機選擇一個32位的序列號(Sequence Number)作為發送數據的初始序列號(Initial Sequence Number,ISN),比如為1000,以該序列號為原點,對要傳送的數據進行編號:1001、1002...三次握手時,把這個初始序列號傳送給另一方B,以便在傳輸數據時,B可以確認什么樣的數據編號是合法的;同時在進行數據傳輸時,A還可以確認B收到的每一個字節,如果A收到了B的確認編號(acknowledge number)是2001,就說明編號為1001-2000的數據已經被B成功接受。
#### 1.7 TCP的四次揮手
##### 1.7.1 什么是TCP的四次揮手
* 在網絡數據傳輸中,傳輸層協議斷開連接的過程我們稱為四次揮手
##### 1.7.2 四次揮手的具體細節

1. 第一次揮手:Client將FIN置為1,發送一個序列號seq給Server;進入FIN\_WAIT\_1狀態;
2. 第二次揮手:Server收到FIN之后,發送一個ACK=1,acknowledge number=收到的序列號+1;進入CLOSE\_WAIT狀態。此時客戶端已經沒有要發送的數據了,但仍可以接受服務器發來的數據。
3. 第三次揮手:Server將FIN置1,發送一個序列號給Client;進入LAST\_ACK狀態;
4. 第四次揮手:Client收到服務器的FIN后,進入TIME\_WAIT狀態;接著將ACK置1,發送一個acknowledge number=序列號+1給服務器;服務器收到后,確認acknowledge number后,變為CLOSED狀態,不再向客戶端發送數據。客戶端等待2\*MSL(報文段最長壽命)時間后,也進入CLOSED狀態。完成四次揮手。
##### 1.7.3 用現實理解三次握手的具體細節TCP的四次揮手
* 四次揮手斷開連接是因為要確定數據全部傳書完了
1. 客戶與服務器交談結束之后,客戶要結束此次會話,就會對服務器說:我要關閉連接了(第一 次揮手)
2. 服務器收到客戶的消息后說:好的,你要關閉連接了。(第二次揮手)
3. 然后服務器確定了沒有話要和客戶說了,服務器就會對客戶說,我要關閉連接了。(第三次揮 手)
4. 客戶收到服務器要結束連接的消息后說:已收到你要關閉連接的消息。(第四次揮手),才關閉
##### 1.7.4 為什么不能把服務器發送的ACK和FIN合并起來,變成三次揮手(CLOSE\_WAIT狀態意義是什么)?
* 因為服務器收到客戶端斷開連接的請求時,可能還有一些數據沒有發完,這時先回復ACK,表示接收到了斷開連接的請求。等到數據發完之后再發FIN,斷開服務器到客戶端的數據傳送。
##### 1.7.5 如果第二次揮手時服務器的ACK沒有送達客戶端,會怎樣?
* 客戶端沒有收到ACK確認,會重新發送FIN請求。
##### 1.7.6 客戶端TIME\_WAIT狀態的意義是什么?
* 第四次揮手時,客戶端發送給服務器的ACK有可能丟失,TIME\_WAIT狀態就是用來重發可能丟失的ACK報文。如果Server沒有收到ACK,就會重發FIN,如果Client在2\*MSL的時間內收到了FIN,就會重新發送ACK并再次等待2MSL,防止Server沒有收到ACK而不斷重發FIN。 MSL(Maximum Segment Lifetime),指一個片段在網絡中最大的存活時間,2MSL就是一個發送和一個回復所需的最大時間。如果直到2MSL,Client都沒有再次收到FIN,那么Client推斷ACK已經被成功接收,則結束TCP連接。
### 2 Socket
#### 1 什么是Socket
* 網絡上的兩個程序通過一個雙向的通訊連接實現數據的交換,這個雙向鏈路的一端稱為一個Socket。Socket通常用來實現客戶方和服務方的連接。Socket是TCP/IP協議的一個十分流行的編程界面,一個Socket由一個IP地址和一個端口號唯一確定。
* 但是,Socket所支持的協議種類也不光TCP/IP、UDP,因此兩者之間是沒有必然聯系的。在Java環境下,Socket編程主要是指基于TCP/IP協議的網絡編程。
* socket連接就是所謂的長連接,客戶端和服務器需要互相連接,理論上客戶端和服務器端一旦建立起連接將不會主動斷掉的,但是有時候網絡波動還是有可能的
* Socket偏向于底層。一般很少直接使用Socket來編程,框架底層使用Socket比較多,

#### 2 socket屬于網絡的那個層面

* Socket是應用層與TCP/IP協議族通信的中間軟件抽象層,它是一組接口。在設計模式中,Socket其實就是一個[外觀模式](https://link.juejin.cn?target=https%3A%2F%2Fblog.csdn.net%2Fweixin_43122090%2Farticle%2Fdetails%2F104904625 "https://blog.csdn.net/weixin_43122090/article/details/104904625"),它把復雜的TCP/IP協議族隱藏在Socket接口后面,對用戶來說,一組簡單的接口就是全部,讓Socket去組織數據,以符合指定的協議。
#### 3 Socket通訊的過程
* 基于TCP:服務器端先初始化Socket,然后與端口綁定(bind),對端口進行監聽(listen),調用accept阻塞,等待客戶端連接。在這時如果有個客戶端初始化一個Socket,然后連接服務器(connect),如果連接成功,這時客戶端與服務器端的連接就建立了。客戶端發送數據請求,服務器端接收請求并處理請求,然后把回應數據發送給客戶端,客戶端讀取數據,最后關閉連接,一次交互結束。
* 基于UDP:UDP 協議是用戶數據報協議的簡稱,也用于網絡數據的傳輸。雖然 UDP 協議是一種不太可靠的協議,但有時在需要較快地接收數據并且可以忍受較小錯誤的情況下,UDP 就會表現出更大的優勢。我客戶端只需要發送,服務端能不能接收的到我不管
#### 4 TCP協議Socket代碼示例:
`先運行服務端,在運行客戶端`,
1. 服務端:
~~~
package com.test.io;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
//TCP協議Socket使用BIO進行通行:服務端
public class BIOServer {
// 在main線程中執行下面這些代碼
public static void main(String[] args) {
//1單線程服務
ServerSocket server = null;
Socket socket = null;
InputStream in = null;
OutputStream out = null;
try {
server = new ServerSocket(8000);
System.out.println("服務端啟動成功,監聽端口為8000,等待客戶端連接...");
while (true){
socket = server.accept(); //等待客戶端連接
System.out.println("客戶連接成功,客戶信息為:" + socket.getRemoteSocketAddress());
in = socket.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
//讀取客戶端的數據
while ((len = in.read(buffer)) > 0) {
System.out.println(new String(buffer, 0, len));
}
//向客戶端寫數據
out = socket.getOutputStream();
out.write("hello!".getBytes());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
復制代碼
~~~
2. 客戶端:
~~~
package com.test.io;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;
//TCP協議Socket:客戶端
public class Client01 {
public static void main(String[] args) throws IOException {
//創建套接字對象socket并封裝ip與port
Socket socket = new Socket("127.0.0.1", 8000);
//根據創建的socket對象獲得一個輸出流
OutputStream outputStream = socket.getOutputStream();
//控制臺輸入以IO的形式發送到服務器
System.out.println("TCP連接成功 \n請輸入:");
while(true){
byte[] car = new Scanner(System.in).nextLine().getBytes();
outputStream.write(car);
System.out.println("TCP協議的Socket發送成功");
//刷新緩沖區
outputStream.flush();
}
}
}
復制代碼
~~~
`先運行服務端,在運行客戶端`。測試結果發送成功:

·

#### 5 UDP協議Socket代碼示例:
`先運行服務端,在運行客戶端`
1. 服務端:
~~~
//UDP協議Socket:服務端
public class Server1 {
public static void main(String[] args) {
try {
//DatagramSocket代表聲明一個UDP協議的Socket
DatagramSocket socket = new DatagramSocket(8888);
//byte數組用于數據存儲。
byte[] car = new byte[1024];
//DatagramPacket 類用來表示數據報包DatagramPacket
DatagramPacket packet = new DatagramPacket(car, car.length);
// //創建DatagramPacket的receive()方法來進行數據的接收,等待接收一個socket請求后才執行后續操作;
System.out.println("等待UDP協議傳輸數據");
socket.receive(packet);
//packet.getLength返回將要發送或者接收的數據的長度。
int length = packet.getLength();
System.out.println("啥東西來了:" + new String(car, 0, length));
socket.close();
System.out.println("UDP協議Socket接受成功");
} catch (IOException e) {
e.printStackTrace();
}
}
}
復制代碼
~~~
2. 客戶端:
~~~
//UDP協議Socket:客戶端
public class Client1 {
public static void main(String[] args) {
try {
//DatagramSocket代表聲明一個UDP協議的Socket
DatagramSocket socket = new DatagramSocket(2468);
//字符串存儲人Byte數組
byte[] car = "UDP協議的Socket請求,有可能失敗喲".getBytes();
//InetSocketAddress類主要作用是封裝端口
InetSocketAddress address = new InetSocketAddress("127.0.0.1", 8888);
//DatagramPacket 類用來表示數據報包DatagramPacket
DatagramPacket packet = new DatagramPacket(car, car.length, address);
//send() 方法發送數據包。
socket.send(packet);
System.out.println("UDP協議的Socket發送成功");
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
復制代碼
~~~
`先運行服務端,在運行客戶端`。測試結果成功發送成功:

#### 6 Socket的常用類
| 類名 | 用于 | 作用 |
| --- | --- | --- |
| Socket | TCP協議 | Socket類同時工作于客戶端和服務端,所有方法都是通用的,這個類三個主要作用,校驗包信息,發起連接(Client),操作流數據(Client/Server) |
| ServerSocket | TCP協議 | ServerSocket表示為服務端,主要作用就是綁定并監聽一個服務器端口,為每個建立連接的客戶端“克隆/映射”一個Socket對象,具體數據操作都是通過這個Socket對象完成的,ServerSocket只關注如何和客戶端建立連接 |
| DatagramSocket | ODP協議 | DatagramSocket 類用于表示發送和接收數據報包的套接字。 |
| DatagramPacket | ODP協議 | DatagramPacket 類用來表示數據報包,數據報包用來實現無連接包投遞服務。 |
| InetAddress | IP+端口號 | Java提供了InetAddress類來代表互聯網協議(IP)地址,InetAddress類沒有提供構造器,而是提供了如下兩個靜態方法來獲取InetAddress實例: |
| InetSocketAddress | IP+端口號 | 在使用Socket來連接服務器時最簡單的方式就是直接使用IP和端口,但Socket類中并未提供這種方式,而是靠SocketAddress的子類InetSocketAddress來實現 IP 地址 + 端口號的創建,不依賴任何協議。 |
### 3\. HTTP
#### 什么是Http協議?
* Http協議是對客戶端和服務器端之間數據之間實現可靠性的傳輸文字、圖片、音頻、視頻等超文本數據的規范,格式簡稱為“超文本傳輸協議”
* Http協議屬于應用層,及用戶訪問的第一層就是http

#### Socket和http的區別和應用場景
* Socket連接就是所謂的長連接,理論上客戶端和服務器端一旦建立起連接將不會主動斷掉;
* Socket適用場景:網絡游戲,銀行持續交互,直播,在線視屏等。
* http連接就是所謂的短連接,即客戶端向服務器端發送一次請求,服務器端響應后連接即會斷開等待下次連接
* http適用場景:公司OA服務,互聯網服務,電商,辦公,網站等等等等
#### 什么是http的請求體?
* HTTP請求體是我們請求數據時先發送給服務器的數據,畢竟我向服務器那數據,先要表明我要什么吧
* HTTP請求體由:請求行 、請求頭、請求數據組成的,
* 注意:GIT請求是沒有請求體的
1. POST請求

2. GIT請求是沒有請求體的  `發現只有請求行和請求頭,少了個請求體`
#### http的響應報文有哪些?
* http的響應報是服務器返回給我們的數據,必須先有請求體再有響應報文
* 響應報文包含三部分 狀態行、響應首部字段、響應內容實體實現

#### http和https的區別?
* 其實HTTPS就是從HTTP加上加密處理(一般是SSL安全通信線路)+認證+完整性保護
* 區別:
1. http需要拿到ca證書,需要錢的
2. 端口不一樣,http是80,https443
3. http是超文本傳輸協議,信息是明文傳輸,https則是具有安全性的ssl加密傳輸協議。
4. http和https使用的是完全不同的連接方式(http的連接很簡單,是無狀態的;HTTPS 協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網絡協議,比http協議安全。)
#### HTTPS工作原理
* 一、首先HTTP請求服務端生成證書,客戶端對證書的有效期、合法性、域名是否與請求的域名一致、證書的公鑰(RSA加密)等進行校驗;
* 二、客戶端如果校驗通過后,就根據證書的公鑰的有效, 生成隨機數,隨機數使用公鑰進行加密(RSA加密);
* 三、消息體產生的后,對它的摘要進行MD5(或者SHA1)算法加密,此時就得到了RSA簽名;
* 四、發送給服務端,此時只有服務端(RSA私鑰)能解密。
* 五、解密得到的隨機數,再用AES加密,作為密鑰(此時的密鑰只有客戶端和服務端知道)。
#### 一次完整的HTTP請求所經歷幾個步驟?
`HTTP通信機制是在一次完整的HTTP通信過程中,Web瀏覽器與Web服務器之間將完成下列7個步驟:`
1. 建立TCP連接
怎么建立連接的,看上面的三次捂手
2. Web瀏覽器向Web服務器發送請求行
一旦建立了TCP連接,**Web瀏覽器就會向Web服務器發送請求命令**。例如:GET /sample/hello.jsp HTTP/1.1。
3. Web瀏覽器發送請求頭
瀏覽器發送其請求命令之后,還要以頭信息的形式向Web服務器發送一些別的信息,**之后瀏覽器發送了一空白行來通知服務器**,它已經結束了該頭信息的發送。
4. Web服務器應答
客戶機向服務器發出請求后,服務器會客戶機回送應答, **HTTP/1.1 200 OK ,應答的第一部分是協議的版本號和應答狀態碼。**
5. Web服務器發送應答頭
正如客戶端會隨同請求發送關于自身的信息一樣,服務器也會隨同應答向用戶發送關于它自己的數據及被請求的文檔。
6. Web服務器向瀏覽器發送數據
Web服務器向瀏覽器發送頭信息后,它會發送一個空白行來表示頭信息的發送到此為結束,接著,**它就以Content-Type應答頭信息所描述的格式發送用戶所請求的實際數據**。
7. Web服務器關閉TCP連接
#### 常用HTTP狀態碼是怎么分類的,有哪些常見的狀態碼?
* HTTP狀態碼表示客戶端HTTP請求的返回結果、標識服務器處理是否正常、表明請求出現的錯誤等。
* 狀態碼的類別:
> | 類別 | 描述 |
> | --- | --- |
> | 1xx: | 指示信息–表示請求已接收,正在處理 |
> | 2xx: | 成功–表示請求已被成功接收、理解、接受 |
> | 3xx: | 重定向–要完成請求必須進行更進一步的操作 |
> | 4xx: | 客戶端錯誤–請求有語法錯誤或請求無法實現 |
> | 5xx: | 服務器端錯誤–服務器未能實現合法的請求 |
* 常見的狀態碼:
> | 狀態碼 | 描述 |
> | --- | --- |
> | 200: | 請求被正常處理 |
> | 204: | 請求被受理但沒有資源可以返回 |
> | 206: | 客戶端只是請求資源的一部分,服務器只對請求的部分資源執行GET方法,相應報文中通過Content-Range指定范圍的資源。 |
> | 301: | 永久性重定向 |
> | 302: | 臨時重定向 |
> | 303: | 與302狀態碼有相似功能,只是它希望客戶端在請求一個URI的時候,能通過GET方法重定向到另一個URI上 |
> | 304: | 發送附帶條件的請求時,條件不滿足時返回,與重定向無關 |
> | 307: | 臨時重定向,與302類似,只是強制要求使用POST方法 |
> | 400: | 請求報文語法有誤,服務器無法識別 |
> | 401: | 請求需要認證 |
> | 403: | 請求的對應資源禁止被訪問 |
> | 404: | 服務器無法找到對應資源 |
> | 500: | 服務器內部錯誤 |
> | 503: | 服務器正忙 |
#### Http協議中有那些請求方式
> | 請求方式 | 描述 |
> | --- | --- |
> | GET: | 用于請求訪問已經被URI(統一資源標識符)識別的資源,可以通過URL傳參給服務器 |
> | POST: | 用于傳輸信息給服務器,主要功能與GET方法類似,但一般推薦使用POST方式。 |
> | PUT: | 傳輸文件,報文主體中包含文件內容,保存到對應URI位置。 |
> | HEAD: | 獲得報文首部,與GET方法類似,只是不返回報文主體,一般用于驗證URI是否有 > 效。 |
> | PATCH: | 客戶端向服務器傳送的數據取代指定的文檔的內容(部分取代) |
> | TRACE: | 回顯客戶端請求服務器的原始請求報文,用于"回環"診斷 |
> | DELETE: | 刪除文件,與PUT方法相反,刪除對應URI位置的文件。 |
> | OPTIONS: | 查詢相應URI支持的HTTP方法。 |
#### GET方法與POST方法的區別
* **區別一**: get重點在從服務器上獲取資源,post重點在向服務器發送數據;
* **區別二**: Get傳輸的數據量小,因為受URL長度限制,但效率較高; Post可以傳輸大量數據,所以上傳文件時只能用Post方式;
* **區別三**: get是不安全的,因為get請求發送數據是在URL上,是可見的,可能會泄露私密信息,如密碼等; post是放在請求頭部的,是安全的
#### http版本的對比
* HTTP1.0版本的特性:
* 早先1.0的HTTP版本,是一種無狀態、無連接的應用層協議。
* HTTP1.0規定瀏覽器和服務器保持短暫的連接,瀏覽器的每次請求都需要與服務器建立一個TCP連接,服務器處理完成后立即斷開TCP連接(無連接),服務器不跟蹤每個客戶端也不記錄過去的請求(無狀態)。
* HTTP1.1版本新特性
* 默認持久連接節省通信量,只要客戶端服務端任意一端沒有明確提出斷開TCP連接,就一直保持連接,可以發送多次HTTP請求
* 管線化,客戶端可以同時發出多個HTTP請求,而不用一個個等待響應
* 斷點續傳原理
* HTTP2.0版本的特性
* 二進制分幀(采用二進制格式的編碼將其封裝)
* 首部壓縮(設置了專門的首部壓縮設計的HPACK算法。)
* 流量控制(設置了接收某個數據流的多少字節一些流量控制)
* 多路復用(可以在共享TCP鏈接的基礎上同時發送請求和響應)
* 請求優先級(可以通過優化這些幀的交錯和傳輸順序進一步優化性能)
* 服務器推送(就是服務器可以對一個客戶端請求發送多個響應。服務器向客戶端推送資 源無需客戶端明確的請求。(重大更新))
#### 什么是對稱加密與非對稱加密
* 對稱密鑰加密是指加密和解密使用同一個密鑰的方式,這種方式存在的最大問題就是密鑰發送問題,即如何安全地將密鑰發給對方;
* 而非對稱加密是指使用一對非對稱密鑰,即公鑰和私鑰,公鑰可以隨意發布,但私鑰只有自己知道。發送密文的一方使用對方的公鑰進行加密處理,對方接收到加密信息后,使用自己的私鑰進行解密。 由于非對稱加密的方式不需要發送用來解密的私鑰,所以可以保證安全性;但是和對稱加密比起來,非常的慢
#### cookie和session對于HTTP有什么用?
* HTTP協議本身是無法判斷用戶身份。所以需要cookie或者session
##### 什么是cookie
* cookie是由Web服務器保存在用戶瀏覽器上的文件(key-value格式),可以包含用戶相關的信息。客戶端向服務器發起請求,就提取瀏覽器中的用戶信息由http發送給服務器
##### 什么是session
* session 是瀏覽器和服務器會話過程中,服務器會分配的一塊儲存空間給session。
* 服務器默認為客戶瀏覽器的cookie中設置 sessionid,這個sessionid就和cookie對應,瀏覽器在向服務器請求過程中傳輸的cookie 包含 sessionid ,服務器根據傳輸cookie 中的 sessionid 獲取出會話中存儲的信息,然后確定會話的身份信息。
##### cookie與session區別
1. cookie數據存放在客戶端上,安全性較差,session數據放在服務器上,安全性相對更高
2. 單個cookie保存的數據不能超過4K,session無此限制 信息后,使用自己的私鑰進行解密。 由于非對稱加密的方式不需要發送用來解密的私鑰,所以可以保證安全性;但是和對稱加密比起來,非常的慢
#### cookie和session對于HTTP有什么用?
* HTTP協議本身是無法判斷用戶身份。所以需要cookie或者session
##### 什么是cookie
* cookie是由Web服務器保存在用戶瀏覽器上的文件(key-value格式),可以包含用戶相關的信息。客戶端向服務器發起請求,就提取瀏覽器中的用戶信息由http發送給服務器
##### 什么是session
* session 是瀏覽器和服務器會話過程中,服務器會分配的一塊儲存空間給session。
* 服務器默認為客戶瀏覽器的cookie中設置 sessionid,這個sessionid就和cookie對應,瀏覽器在向服務器請求過程中傳輸的cookie 包含 sessionid ,服務器根據傳輸cookie 中的 sessionid 獲取出會話中存儲的信息,然后確定會話的身份信息。
##### cookie與session區別
1. cookie數據存放在客戶端上,安全性較差,session數據放在服務器上,安全性相對更高
2. 單個cookie保存的數據不能超過4K,session無此限制
3. session一定時間內保存在服務器上,當訪問增多,占用服務器性能,考慮到服務器性能方面,應當使用cookie。
- 常見面試題
- 一.Java常見面試題
- 1.Java基礎
- 3.面向對象概念
- 10.Java面試題
- Java基礎知識面試題(總結最全面的面試題)
- 設計模式面試題(總結最全面的面試題)
- Java集合面試題(總結最全面的面試題)
- JavaIO、BIO、NIO、AIO、Netty面試題(總結最全面的面試題)
- Java并發編程面試題(總結最全面的面試題)
- Java異常面試題(總結最全面的面試題)
- Java虛擬機(JVM)面試題(總結最全面的面試題)
- Spring面試題(總結最全面的面試題)
- Spring MVC面試題(總結最全面的面試題)
- Spring Boot面試題(總結最全面的面試題)
- Spring Cloud面試題(總結最全面的面試題)
- Redis面試題(總結最全面的面試題)
- MyBatis面試題(總結最全面的面試題)
- TCP、UDP、Socket、HTTP面試題(總結最全面的面試題)
- 二、MySQL面試題
- 1.基礎部分
- MySQL面試題(總結最全面的面試題)
- HBase相關面試題整理
- Nginx面試題(總結最全面的面試題)
- RabbitMQ面試題(總結最全面的面試題)
- Dubbo面試題(總結最全面的面試題)
- ZooKeeper面試題(總結最全面的面試題)
- Tomcat面試題(總結最全面的面試題)
- Linux面試題(總結最全面的面試題)
- 超詳細的Django面試題
- SSM面試題
- 15個高頻微信小程序面試題
- VUE面試題
- Python面試題
- 二、常見問題解答列表
- 1.查看端口及殺死進程
- 三、學習電子書