計(jì)算機(jī)網(wǎng)絡(luò)面試核心
傳輸層控制協(xié)議 TCP 簡介
- 傳輸層控制協(xié)議 TCP 簡介
- 面向連接的,可靠的,基于字節(jié)流的傳輸層通信協(xié)議
- 將應(yīng)用層的數(shù)據(jù)流分割成報(bào)文段并發(fā)送給目標(biāo)結(jié)點(diǎn)的TCP層
- 數(shù)據(jù)包都有序號,對方收到則發(fā)送ACK確認(rèn),未收到則重傳
- 使用校驗(yàn)和來檢驗(yàn)數(shù)據(jù)在傳輸過程中是否有誤
- 報(bào)文頭格式

TCP Flags:
1. URG:緊急指針標(biāo)志
2. ACK:確認(rèn)序號標(biāo)志
3. PSH:push標(biāo)志
4. RST:重制連接標(biāo)志
5. SYN:同步序號,用于建立連接過程
6. FIN:finish標(biāo)志,用于釋放連接
TCP三次握手

Question: 說說TCP的三次握手
"握手”是為了建立連接, TCP三次握手的流程圖如下:
在TCP/IP協(xié)議中,TCP協(xié)議提供可靠的連接服務(wù),采用三次握手建立一個(gè)連接。
第一次握手:建立連接時(shí),客戶端發(fā)送SYN包[syn=j)到服務(wù)器,并進(jìn)入SYN_SEND狀態(tài),等待服務(wù)器確認(rèn);
第二次握手:服務(wù)器收到SYN 包,必須確認(rèn)客戶的SYN(ack=j+1) ,同時(shí)自己也發(fā)送一個(gè)SYN 包(syn=k) ,即
SYN+ACK包,此時(shí)服務(wù)器進(jìn)入SYN_ RECV狀態(tài);
第三次握手:客戶端收到服務(wù)器的SYN+ACK包,向服務(wù)器發(fā)送確認(rèn)包ACK(ack=k+1),此包發(fā)送完畢,客戶端和服務(wù)器進(jìn)入
ESTABLISHED狀態(tài),完成三次握手。
Question: 為什么需要三次握手才能建立起連接
為了初始化Sequence Number的初始值
Question: 針對SYN Flood的防護(hù)措施
首次握手的隱患---SYN超時(shí)
?SYN隊(duì)列滿后,通過tcp_ syncookies參數(shù)回發(fā)SYN Cookie
?若為正常連接則Client會回發(fā)SYN Cookie ,直接建立連接
Question:建立連接后, Client出現(xiàn)故障怎么辦
?;顧C(jī)制
?向?qū)Ψ桨l(fā)送保活探測報(bào)文,如果未收到響應(yīng)則繼續(xù)發(fā)送
?嘗試次數(shù)達(dá)到?;钐綔y數(shù)仍未收到響應(yīng)則中斷連接
談?wù)凾CP的四次揮手
“揮手”是為了終止連接,TCP四次揮手的流程圖如下:

服務(wù)器 CLOSE-WAIT:半關(guān)閉狀態(tài),客戶端已經(jīng)沒有數(shù)據(jù)發(fā)送了,但是服務(wù)器發(fā)送的數(shù)據(jù)還是可以接收到
Question:談?wù)凾CP的四次揮手
"揮手”是為了終止連接, TCP四次揮手的流程圖如下:
第一次揮手: Client發(fā)送-一個(gè)FIN,用來關(guān)閉Client到Server的數(shù)據(jù)傳送,Client 進(jìn)入FIN_WAIT_1狀態(tài);
第二次揮手: Server 收到FIN后,發(fā)送一個(gè)ACK給Client,確認(rèn)序號為收到序號+1 (與SYN相同,一個(gè)FIN占用一個(gè)序
號),Server 進(jìn)入CLOSE WAIT狀態(tài);
第三次揮手: Server發(fā)送- -個(gè)FIN,用來關(guān)閉Server到Client的數(shù)據(jù)傳送,Server 進(jìn)入LAST ACK狀態(tài);
第四次揮手: Client 收到FIN后,Client 進(jìn)入TIME_WAIT狀態(tài),接著發(fā)送一個(gè)ACK給Server,確認(rèn)序號為收到序號+1,Server進(jìn)入CLOSED狀態(tài),完成四次揮手。
Question: 為什么會有TIME_WAIT狀態(tài)
- 確保有足夠的時(shí)間讓對方收到ACK包
- 避免新舊連接混淆
Question:為什么需要四次揮手才能斷開連接
因?yàn)槿p工,發(fā)送方和接收方都需要FIN報(bào)文和ACK報(bào)文
Question:服務(wù)器出現(xiàn)大量CLOSE_ WAIT狀態(tài)的原因
對方關(guān)閉socket連接,我方忙于讀或?qū)?沒有及時(shí)關(guān)閉連接
?檢查代碼,特別是釋放資源的代碼
?檢查配置,特別是處理請求的線程配置
UDP 簡介

Question:UDP特點(diǎn)
- 面向非連接
- 不維護(hù)連接狀態(tài),支持同時(shí)向多個(gè)客戶端傳輸相同的消息
- 數(shù)據(jù)包報(bào)頭只有8個(gè)字節(jié),額外開銷較小
- 吞吐量只受限于數(shù)據(jù)生成速率、傳輸速率以及機(jī)器性能
- 盡最大努力交付,不保證可靠交付,不需要維持復(fù)雜的鏈接狀態(tài)表
- 面向報(bào)文,不對應(yīng)用程序提交的報(bào)文信息進(jìn)行拆分或者合并
Question: TCP與UDP的區(qū)別
- 面向連接vs無連接
- 可靠性
- 有序性
- 速度
- 量級
TCP的滑動(dòng)窗口
Question:RTT和RTO
?RTT :發(fā)送一個(gè)數(shù)據(jù)包到收到對應(yīng)的ACK ,所花費(fèi)的時(shí)間
?RTO :重傳時(shí)間間隔
Question:tcp使用滑動(dòng)窗口做流量控制與亂序重排的作用
- 保證TCP的可靠性
- 保證TCP的流控特性
window:通知發(fā)送方自己能接收的數(shù)據(jù)域
HTTP簡介
Question:超本文傳輸協(xié)議HTTP主要特點(diǎn)
- 支持客戶/服務(wù)器模式
- 簡單/快速
- 靈活
- 無連接
- 無狀態(tài)
Question:HTTP請求結(jié)構(gòu)

【請求行,請求頭部,空行,請求正文】
Question:請求/響應(yīng)的步驟
- 客戶端連接到Web服務(wù)器
- 發(fā)送HTTP請求
- ?服務(wù)器接受請求并返回HTTP響應(yīng)
- 釋放連接TCP連接
- ?客戶端瀏覽器解析HTML內(nèi)容
Question:在瀏覽器地址欄鍵入U(xiǎn)RL,按下回車之后經(jīng)歷的流程
- DNS解析
- TCP連接
- 發(fā)送HTTP請求
- 服務(wù)器處理請求并返回HTTP報(bào)文
- 瀏覽器解析渲染頁面
- 連接結(jié)束
Question:HTTP狀態(tài)碼
?1xx :指示信息--表示請求E接收,繼續(xù)處理
?2xx :成功--表示請求已被成功接收、理解、接受
?3xx :重定向--要完成請求必須進(jìn)行更進(jìn)一 步的操作
?4xx :客戶端錯(cuò)誤--請求有語法錯(cuò)誤或請求無法實(shí)現(xiàn)
?5xx :服務(wù)器端錯(cuò)誤--服務(wù)器未能實(shí)現(xiàn)合法的請求
Question:常見狀態(tài)碼
200 OK:正常返回信息
400 Bad Request:客戶端請求有語法錯(cuò)誤,不能被服務(wù)器所理解
401 Unauthorized:請求未經(jīng)授權(quán),這個(gè)狀態(tài)代碼必須和
WWW-Authenticate報(bào)頭域一起 使用
403 Forbidden:服務(wù)器收到請求,但是拒絕提供服務(wù)
404 Not Found:請求資源不存在,eg, 輸入了錯(cuò)誤的URL
500 Internal Server Error:服務(wù)器發(fā)生不可預(yù)期的錯(cuò)誤
503 Server Unavailable:服務(wù)器當(dāng)前不能處理客戶端的請求,一段時(shí)間后可能恢復(fù)正常
Question:GET請求與POST請求的區(qū)別
從三個(gè)層面來解答
?Http報(bào)文層面: GET將請求信息放在URL , POST放在報(bào)文體中
?數(shù)據(jù)庫層面: CET符合冪等性和安全性, POST不符合
?其他層面: GET可以被緩存、被存儲,而POST不行
Question:Cookie和Session的區(qū)別
Cookie簡介
?是由服務(wù)器發(fā)給客戶端的特殊信息,以文本的形式存放在客戶端
?客戶端再次請求的時(shí)候,會把Cookie回發(fā)
?服務(wù)器接收到后,會解析Cookie生成與客戶端相對應(yīng)的內(nèi)容

Session簡介
?服務(wù)器端的機(jī)制,在服務(wù)器上保存的信息
?解析客戶端請求并操作session id ,按需保存狀態(tài)信息

?Cookie數(shù)據(jù)存放在客戶的瀏覽器上, Session數(shù)據(jù)放在服務(wù)器上
Session相對于Cookie更安全
若考慮減輕服務(wù)器負(fù)擔(dān),應(yīng)當(dāng)使用Cookie
HTTP與HTTPS的區(qū)別

Question:SSL(Security Sockets Layer ,安全套接層)
?為網(wǎng)絡(luò)通信提供安全及數(shù)據(jù)完整性的一種安全協(xié)議
?是操作系統(tǒng)對外的API , SSL3.0后更名為TLS
?采用身份驗(yàn)證和數(shù)據(jù)加密保證網(wǎng)絡(luò)通信的安全和數(shù)據(jù)的完整性
Question:加密的方式
?對稱加密:加密和解密都使用同一個(gè)密鑰
?非對稱加密:加密使用的密鑰和解密使用的密鑰是不相同的
?哈希算法:將任意長度的信息轉(zhuǎn)換為固定長度的值,算法不可逆
?數(shù)字簽名:證明某個(gè)消息或者文件是某人發(fā)出/認(rèn)同的
Question:HTTPS數(shù)據(jù)傳輸流程
?瀏覽器將支持的加密算法信息發(fā)送給服務(wù)器
?服務(wù)器選擇一套瀏覽器支持的加密算法,以證書的形式回發(fā)瀏覽器
?瀏覽器驗(yàn)證證書合法性,并結(jié)合證書公鑰加密信息發(fā)送給服務(wù)器
?服務(wù)器使用私鑰解密信息,驗(yàn)證哈希,加密響應(yīng)消息回發(fā)瀏覽器
?瀏覽器解密響應(yīng)消息,并對消息進(jìn)行驗(yàn)真,之后進(jìn)行加密交互數(shù)據(jù)
Question:HTTP與HTTPS的區(qū)別
?HTTPS需要到CA申請證書, HTTP不需要
?HTTPS密文傳輸, HTTP明文傳輸
?連接方式不同, HTTPS默認(rèn)使用443端口, HTTP使用80端口
?HTTPS=HTTP+加密+認(rèn)證+完整性保護(hù),較HTTP安全
Question:HTTPS真的很安全嗎
那倒未必
?瀏覽器默認(rèn)填充http:// ,請求需要進(jìn)行跳轉(zhuǎn),有被劫持的風(fēng)險(xiǎn)
?可以使用HSTS ( HTTP Strict Transport Security )優(yōu)化
Socket簡介
Socket是對TCP/IP協(xié)議的抽象,是操作系統(tǒng)對外開放的接口

Socket通信流程

Question:編寫一個(gè)網(wǎng)絡(luò)應(yīng)用程序,有客戶端與服務(wù)器端,客戶端向服務(wù)器發(fā)送-一個(gè)字符串,服務(wù)器收到該字符串后將其打印到命令行上,然后向客戶端返回該字符串的長度,最后,客戶端輸出服務(wù)器端返回的該字符串的長度,分別用TCP和UDP兩種方式去實(shí)現(xiàn)
public class LengthCalculator extends Thread{
private Socket socket;
public LengthCalculator(Socket socket){
this.socket=socket;
}
@Override
public void run(){
try{
OutputStream os =socket.getOutputStream();
InputStream is =socket.getInputStream();
int ch=0;
byte[] buff =new byte[1024];
ch=is.read(buff);
String content =new String(buff,0,ch);
System.out.println(content);
os.write(String.valueOf(content.length()).getBytes());
is.close();
os.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class TCPClient {
public static void main(String[] args) throws IOException {
Socket socket =new Socket("127.0.0.1",65000);
OutputStream os =socket.getOutputStream();
InputStream is =socket.getInputStream();
os.write(new String("hello world").getBytes());
int ch=0;
byte[] buff =new byte[1024];
ch=is.read(buff);
String content =new String(buff,0,ch);
System.out.println(content);
is.close();
os.close();
socket.close();
}
}
public class TCPServer {
public static void main(String[] args) throws IOException {
ServerSocket ss =new ServerSocket(65000);
while(true){
Socket socket=ss.accept();
new LengthCalculator(socket).start();
}
}
}
public class UDPClient {
public static void main(String[] args) throws IOException {
DatagramSocket socket =new DatagramSocket();
byte[] buf ="hello world".getBytes();
//將IP封裝為InetAddress對象
InetAddress address =InetAddress.getByName("127.0.0.1");
//將要發(fā)送數(shù)據(jù)封裝成DatagramPacket對象,填寫上ip地址與端口號
DatagramPacket packet =new DatagramPacket(buf,buf.length,address,65001);
socket.send(packet);
byte[] data =new byte[100];
//創(chuàng)建DatagramPacket對象來存儲服務(wù)端發(fā)送的數(shù)據(jù)
DatagramPacket receivedPacket = new DatagramPacket(data,data.length);
socket.receive(receivedPacket);
//將數(shù)據(jù)取出來并打印
String content = new String(receivedPacket.getData(),0,receivedPacket.getLength());
System.out.println(content);
}
}
public class UDPServer {
public static void main(String[] args) throws IOException {
//服務(wù)端接收客戶端發(fā)送的數(shù)據(jù)報(bào)
DatagramSocket socket =new DatagramSocket(65001);
//存儲從客戶端收到的內(nèi)容
byte[] buff =new byte[100];
//接收客戶端發(fā)送的內(nèi)容,并將內(nèi)容封裝進(jìn)DatagramPacket對象中
DatagramPacket packet =new DatagramPacket(buff,buff.length);
socket.receive(packet);
//從DatagramPacket中獲取真正存儲的數(shù)據(jù)
byte[] data =packet.getData();
//將數(shù)據(jù)從二進(jìn)制轉(zhuǎn)化為字符串形式
String content =new String(data,0,packet.getLength());
System.out.println(content);
//將要發(fā)送給客戶端的數(shù)據(jù)換成二進(jìn)制
byte[] sendedContent =String.valueOf(content.length()).getBytes();
//服務(wù)端給客戶端發(fā)送數(shù)據(jù)報(bào)
//從DatagramPacket對象中獲取到數(shù)據(jù)的來源地址與端口號
DatagramPacket packetToClient =new DatagramPacket(sendedContent,sendedContent.length,packet.getAddress(),packet.getPort());
socket.send(packetToClient);
}
}