網絡協議與計算機網絡體系結構
知識點總結
-
網絡中計算機的硬件和軟件存在各種差異,爲了保證相互通信及雙方能夠正確地接收信息,必須事先形成一種約定,即網絡協議。協議是指通信雙方必須遵循的、控制信息交換的規則的集合,是一套語義和語法規則,用來規定有關功能部件在通信過程中的操作,它定義了數據發送和接收工作中必經的過程。協議規定了網絡中使用的格式、定時方式、順序和差錯控制。一般說,一個網絡協議主要由語法、語義和同步三個要素組成。
-
計算機網絡體系結構是計算機網絡的各層及其服務和協議的集合,也就是它們所應完成的所有功能的定義,是用戶進行網絡互連和通信系統設計的基礎。
-
OSI七層模型從下到上分別爲物理層、數據鏈路層、網絡層、傳輸層、會話層、表示層和應用層。類似於OSI-RM層次模型,TCP/IP的層次結構包含了四個層次,從下到上分別爲網絡接入層、互連網絡層、傳輸層和應用層。它們有一定的對應關係。
-
協議各層間存在信息交換,一個系統中的相鄰兩個層次間的信息交換是通過服務訪問點這樣的接口實現的。每一層和相鄰層有接口,較低層通過接口向它的上一層提供服務,但這一服務的實現細節對上層是屏蔽的。較高層又是在較低層提供的低級服務的基礎上實現更高級的服務。
-
目前在國際上最著名的兩個國際標準化組織分別是
ISO
和ITU-T
。ITU-T
主要負責電話和數字通信領域的建議和標準。因特網的標準化工作由稱爲IAB
的組織負責,下設Task Force
負責具體的某一方面標準,如IETF
負責因特網近期發展的工程與標準問題。有關文檔成爲RFC
。如著名的 IP 協議和 TCP 協議的文檔爲RFC791
和RFC793
。
網絡協議與分層體系結構
協議:是指通信雙方必須遵循的、控制信息交換的規則的集合,是一套語義和語法規則,用來規定有關功能部件在通信過程中的操作,它定義了數據發送和接收工作中必經的過程。協議規定了網絡中使用的格式、定時方式、順序和檢錯。
協議的組成:語法、語義、同步
網絡體系結構:計算機網絡的分層、每層的功能以及每層使用到的協議的集合。
協議層次模型:下層爲上層提供服務
開放系統互連參考模型OSI/RM
爲了更好地促進互聯網絡的研究和發展,國際標準化組織 ISO 在 1985 年制定了網絡互連模型
- OSI 參考模型(Open System Interconnect Reference Model),具有 7 層結構
五層的體系結構
- 應用層:直接爲用戶的應用進程提供服務
例如萬維網服務需要HTTP
協議,電子郵件需要SMTP
、MIME
等協議,QQ聊天等應用進程。 - 傳輸層:爲兩臺主機中進程之間的通信提供服務
注意是進程,因此socket編程中需要IP和端口號,因爲每個進程的端口號不同。
- 網絡層:爲網絡上的不同主機之間提供分組的傳輸服務
- 數據鏈路層:將源計算機網絡層來的數據可靠的傳輸到相鄰節點的目標計算機的網絡層。
- 物理層:透明的傳送比特流。
【例】主機甲向主機乙發送數據
實體和服務訪問點SAP
- 實體:表示任何可以發送和接收信息的硬件或者軟件進程。
- 服務訪問點(SAP):指相鄰兩層交換信息的地方。
PDU:協議數據單元
TCP/IP體系結構
主機A:
- 應用層:直接爲用戶的應用進程提供服務。
- 傳輸層:負責爲兩臺主機中的各個應用程序之間提供通信服務。
- 互連網絡層: 負責獨立地將分組從源主機送往目的主機,爲分組提供最佳路由選擇和交換功能。
- 網絡接入層: 它負責接收從網絡層交付的IP分組,並將IP分組封裝在幀中,通過底層的物理網絡發送出去。
TCP/IP 協議棧
沙漏計時器形狀的TCP/IP協議族
兩者的區別
出發點不同 :
OSI-RM
是作爲國際標準而制定的,不得不兼顧各方,考慮各種情況,造成OSI-RM
相對比較複雜,協議的數量和複雜性都遠高於TCP/IP
。
• 早期TCP/IP
協議是爲軍用網ARPANET
設計的體系結構,一開始就考慮了一些特殊要求,如可用性,殘存性,安全性,網絡互聯性以及處理瞬間大信息量的能力等。
對一些問題的處理方法不同 :
- 對層次間的關係:
OSI-RM
模型嚴格按層次結構,而TCP/IP
可以跨層; - 無連接服務問題 :
OSI-RM
模型只考慮面向連接的服務,而TCP/IP
同時還考慮無連接服務。
網絡通信標準化組織
- ISO(1947年成立)
- ITU(1865年成立)
因特網的標準化工作
RFC (Request For Comments),是一系列以編號排定的文件。文件收集了有關互聯網相關信息,以及UNIX和互聯網社區的軟件文件。RFC文件是由Internet Society(ISOC)贊助發行。基本的互聯網通信協議都有在RFC文件內詳細說明。RFC文件還額外加入許多在標準內的論題,例如對於互聯網新開發的協議及發展中所有的記錄。因此幾乎所有的互聯網標準都有收錄在RFC文件之中。
【補充】TCP/IP 協議
TCP/IP
協議,簡稱 TCP/IP
- 是一個網絡通信模型,以及一整個網絡傳輸協議家族,爲網際網絡的基礎通信架構
TCP/IP
不僅僅指的是 TCP
和 IP
兩個協議
- 是指一個由
FTP
、SMTP
、TCP
、UDP
、IP
等協議構成的協議家族 TCP
、IP
協議是該協議家族中最早通過的標準,所以稱爲TCP/IP
TCP
:Transmission Control Protocol,傳輸控制協議
IP
:Internet Protocol,網際協議
TCP vs UDP
TCP 數據
在 Java 中,使用 java.net.Socket
、java.net.ServerSocket
可以實現 TCP 請求
UPD 數據
在 Java 中,使用 java.net.DatagramSocket
可以實現 UDP
請求
TCP - 三次握手 - 建立連接
TPC - 四次揮手 - 釋放連接
OSI/RM和TCP/IP體系結構的比較
Java網絡編程模擬人工智障聊天(狗頭)
服務端代碼
package com.mj;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServer {
public static void main(String[] args) throws Exception {
try(ServerSocket server = new ServerSocket(8888)){
while(true){
Socket client = server.accept();
new Thread(() -> {
try {
doClient(client);
client.close();
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
}
static void doClient(Socket client) throws Exception{
try(
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = client.getInputStream();
OutputStream os = client.getOutputStream();
){
// 讀取客戶端數據
byte[] buffer = new byte[8192];
int len;
while((len = is.read(buffer)) != -1){
baos.write(buffer, 0, len);
}
byte[] bytes = baos.toByteArray();
String content = new String(bytes, "UTF-8");
String ip = client.getInetAddress().getHostAddress();
System.out.format("服務器接收到[%s]的數據:%s\n", ip, content);
// 寫數據給客戶端
os.write(doString(content).getBytes("UTF-8"));
}
}
static String doString(String str){
str = str.replace("你", "朕");
str = str.replace("嗎", "");
str = str.replace("麼", "朕");
str = str.replace("?", "!");
str = str.replace("?", "!");
return str;
}
public static void test() throws IOException{
ServerSocket serverSocket = new ServerSocket(8888);
Socket socket = serverSocket.accept();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = socket.getInputStream();
byte[] buffer = new byte[8192];
int len;
while((len = is.read(buffer)) != -1){
baos.write(buffer, 0, len);
}
byte[] bytes = baos.toByteArray();
String string = new String(bytes, "UTF-8");
System.out.format("服務器接收到[%s]的數據:%s\n",
socket.getInetAddress(), string);
is.close();
baos.close();
socket.close();
serverSocket.close();
}
}
客戶端代碼
隨便搭了個界面,搞笑用的。
package com.mj;
import java.awt.BorderLayout;
import java.awt.Font;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class MyFrame extends JFrame {
public MyFrame(){
setBounds(300, 300, 400, 200);
setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel panel = new JPanel(new BorderLayout());
setContentPane(panel);
// 字體
Font font = new Font("微軟雅黑", Font.PLAIN, 30);
JLabel label = new JLabel();
label.setFont(font);
panel.add(label, BorderLayout.CENTER);
JTextField tf = new JTextField(10);
tf.setFont(font);
panel.add(tf, BorderLayout.SOUTH);
JButton sendBtn = new JButton("發送");
sendBtn.setFont(font);
sendBtn.addActionListener((evt) -> {
try(
Socket socket = new Socket("127.0.0.1", 8888);
OutputStream os = socket.getOutputStream();
InputStream is = socket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
) {
// 寫數據到服務器
os.write(tf.getText().getBytes("UTF-8"));
// 關閉輸出(表明寫給服務器的內容都寫完了)
socket.shutdownOutput();
// 讀取服務器數據
byte[] buffer = new byte[8192];
int len;
while((len = is.read(buffer)) != -1){
baos.write(buffer, 0, len);
}
byte[] bytes = baos.toByteArray();
String content = new String(bytes, "UTF-8");
label.setText("人工智障:" + content);
} catch (Exception e) {
e.printStackTrace();
}
});
panel.add(sendBtn, BorderLayout.EAST);
}
}
package com.mj;
import java.io.IOException;
public class TCPClient {
public static void main(String[] args) throws Exception, IOException {
MyFrame myFrame = new MyFrame();
myFrame.setTitle("對方是人工智障");
myFrame.setVisible(true);
/* Socket socket = new Socket("127.0.0.1", 8888);
OutputStream os = socket.getOutputStream();
os.write("嘿嘿嘿".getBytes("UTF-8"));
os.close();
socket.close();
*/
}
}