認識傳輸層協議—TCP/UDP

小白的含金量 2022-07-24 02:10:39 阅读数:905

tcpudp

目錄

傳輸層的兩個重要協議

UDP:用戶報文協議

TCP:傳輸控制協議

UDP與TCP對比

相同點:

不同點:

五元組信息

套接字(Socket)

Java中使用的UDP協議

class DatagramSocket (報文套接字) : 用於UDP通信

1.UDP服務器

2.UDP客戶端

3.接收及發送

4.關閉

class DatagramPakcet(報文包):通信過程中的數據抽象

1.接收方

2.發送方

3.一般用作服務器的方法

4.一般用作接收者的方法

服務器與客戶端

常見模式

1.請求(Request)-響應(Response)模式

2.訂閱(subsrcipt) - 廣播(broadcase)模式

UDP總結

TCP

1.構造方法

作為服務器,我們要創建自己的Socket對象

使用Socket對象

2.accept

3.close

4.Socket獲得通信信息

5.輸入流

6.輸出流

關於輸入輸出流的使用

面向數據報文和面向字節流的區別 


傳輸層的兩個重要協議

首先要明確,現在要說的UDP,和馬上要說的TCP,都是在傳輸層工作的協議種類。

UDP:用戶報文協議

傳輸層協議,需要實現進程 to 進程間的通信。

使用UDP協議的兩端並未真正連接起來,只是進行數據的傳播而已。

UDP沒有做過任何處理,就保持網絡的原生態狀態,沒有保護網絡的作用,所以不可靠。

TCP:傳輸控制協議

傳輸層協議,需要實現進程 to 進程間的通信。

使用TCP協議會將服務器與客戶端連接起來。

TCP會做一定的傳輸控制,讓通信變得可靠起來。

UDP與TCP對比

相同點:

都是傳輸層協議,需要實現進程 to 進程間的通信。

不同點:

UDP:不可靠,無連接,面向數據報文的一種協議。

TCP:可靠,有連接,面向字節流的一種協議。

五元組信息

通信雙方IP地址 + 雙方port(端口)地址 + 傳輸層協議 = 五元組信息。

通過五元組信息便可唯一確定網絡上的一條通信線路

套接字(Socket)

Socket關鍵字是站在應用層,做網絡編程的一個很重要的概念。

簡單來說,在應用層以下,由電腦操作系統硬件來提供通信,

而應用層想要使用網絡服務,需要使用OS提供的網絡服務窗口 Socket 來享受服務。


Java中使用的UDP協議

class DatagramSocket (報文套接字) : 用於UDP通信

這個類也就是Socket類的一個子類,複制UDP通信,有兩種構造方法,

一種帶端口參數,用於服務器

一種無參構造,用於客戶端

1.UDP服務器

我們使用Socket構造方法創建對象用於服務器端通信

DatagramSocket socket = new DatagramSocket(PORT);

采用一個固定的端口,以方便客戶端進行通信,可能會有錯誤的風險,比如想要通信的時候發現端口被別的進程占用了。

2.UDP客戶端

依舊是Socket構造方法,但是不需要傳參,我們只作為客戶端發送數據給服務器,並且接收服務器回複來的數據即可。

DatagramSocket socket = new DatagramSocket();

3.接收及發送

發送的內容是接下來要講的報文包類

//接收方法
socket.receive(receivedPacket);
//發送方法
socket.send(sentPacket);

4.關閉

用完之後,記得關閉

socket.close();

class DatagramPakcet(報文包):通信過程中的數據抽象

這個東西相當於就是Socket類要發送的數據包

裏面包含了五元組信息 和 數據內容

1.接收方

僅僅是接收一個信件,所以只需要拿一個byte包接收即可。

// 1. 接收請求
byte[] buf = new byte[1024]; // 1024 代錶我們最大接收的數據大小(字節)
DatagramPacket receivedPacket = new DatagramPacket(buf, buf.length);

2.發送方

發送方需要提供當前數據內容,已經對方的IP和port

 DatagramPacket sentPacket = new DatagramPacket(
bytes, 0, bytes.length, // 要發送的數據
loopbackAddress, TranslateServer.PORT // 對方的 ip + port
);

3.一般用作服務器的方法

 InetAddress address = receivedPacket.getAddress();
Log.println("對方的 IP 地址: " + address);
// 拆出對方的端口
int port = receivedPacket.getPort();
Log.println("對方的 port: " + port);
// 拆出對方的 ip 地址 + port
SocketAddress socketAddress = receivedPacket.getSocketAddress();

我們可以得到接收新建的 port , ip 以及數據。

得到port和ip就可以把數據發送回去,所以這是服務器的常用方法。

 InetAddress address = receivedPacket.getAddress();
Log.println("對方的 IP 地址: " + address);
// 拆出對方的端口
int port = receivedPacket.getPort();
Log.println("對方的 port: " + port);

有了這些,我們可以把數據再發送回去

首先得到對方的信息

// 拆出對方的 ip 地址 + port
SocketAddress socketAddress = receivedPacket.getSocketAddress();

然後再用Packet打包發送回去

DatagramPacket sentPacket = new DatagramPacket(
sendBuf, 0, sendBuf.length, // 要發送的數據
socketAddress // 從請求信封中拆出來的對象的地址(ip + port)
);

4.一般用作接收者的方法

接收者需要數據,所以getData方法比較常用

byte[] data = receivedPacket.getData();

服務器與客戶端

服務器一般是站在應用層角度說的,為目標提供服務

客戶端就是享受服務的一端

常見模式

1.請求(Request)-響應(Response)模式

一次請求,一次響應

這個就是說,客戶端發送請求,服務器接收並響應,在這個過程中服務器是被動的。

下圖是單純的發送更新情况,沒有客戶端,服務器之分,由發送端發送數據,接收端接收並更新數據。

 下圖更符合服務器與客戶端之間的交互,客戶端先發數據到服務器,經過服務器一系列處理再發回客戶端。

 通信數據都是采用二進制數據的方式通信,在這裏錶現為byte[]方式傳播。

2.訂閱(subsrcipt) - 廣播(broadcase)模式

客戶端一次訂閱,服務器會定期主動推送信息給客戶端。

這裏的服務器相對來說主動。

UDP總結

1.網絡編程的情况

2.如何使用ip + port

3.socket的使用

4.UDP的特點:不可靠,無連接,面向數據報文(數據內容在經過通信時不進行拆封,也就是我不會打開這封信,也就不存在數據改變的問題,對方可以完整接收到數據,當然前提是傳出去了)

TCP

TCP是一種可靠,有連接,面向字節流的協議

1.構造方法

作為服務器,我們要創建自己的Socket對象

使用ServerSocket對象

ServerSocket serverSocket = new ServerSocket(PORT);

作為客戶端要連接上服務器

使用Socket對象

 // 直接創建 Socket,使用服務器 IP + PORT
Log.println("准備創建 socket(TCP 連接)");
Socket socket = new Socket("127.0.0.1", TranslateServerShortConnection.PORT);

2.accept

服務器的Socket對象就是接收客戶端得到的,不需要自己創建

監聽客戶端端口,一旦有客戶端連接,返回一個服務器端的Socket對象,並且與此客戶端一直相連直到關閉,在此過程其他客戶端只能阻塞等待。

 Log.println("等待對方來連接");
Socket socket = serverSocket.accept();
Log.println("有客戶端連接上來了");

Socket對象就相當於建立起的連接:

3.close

 客戶端和服務器均可調用此方法來關閉通信

socket.close();

4.Socket獲得通信信息

當服務端獲取到Socket對象時,便可以調用方法來確定對方的信息。

 // 對方信息:
InetAddress inetAddress = socket.getInetAddress(); // ip
Log.println("對方的 ip: " + inetAddress);
int port = socket.getPort(); // port
Log.println("對方的 port: " + port);
SocketAddress remoteSocketAddress = socket.getRemoteSocketAddress(); // ip + port
Log.println("對方的 ip + port: " + remoteSocketAddress);

5.輸入流

當接收端接收信息時,就要用輸入流接收

InputStream inputStream = socket.getInputStream();
Scanner scanner = new Scanner(inputStream, "UTF-8");

6.輸出流

發送數據使用輸出流

 OutputStream os = socket.getOutputStream();
OutputStreamWriter osWriter = new OutputStreamWriter(os, "UTF-8");
PrintWriter writer = new PrintWriter(osWriter);

關於輸入輸出流的使用

面向數據報文和面向字節流的區別 

版权声明:本文为[小白的含金量]所创,转载请带上原文链接,感谢。 https://gsmany.com/2022/205/202207240209553243.html