目錄
1.TCP和UDP的特點及區別
1.1TCP的特點
?1.2UDP的特點
?1.3區別
2.UDP Socket的api的介紹
2.1DatagramSocket API
2.2DatagramPacket API ?
3.回顯客戶端與服務器
3.1回顯服務器
3.1.1UdpEchoServer類的創建
3.1.2服務器的運行方法start()
3.1.3main部分
?3.1.4.完整代碼
?3.2回顯客戶端
3.2.1UdpEchoClient類的創建
?3.2.2客戶端的運行方法start()
3.2.3main部分?
3.2.4?完整代碼
1.TCP和UDP的特點及區別
想要進行網絡編程,都需要使用到系統的API。本質上都是傳輸層提供的。傳輸層涉及到的協議主要有兩個。TCP和UDP,他倆的api差異很大。
TCP和UDP都是Socket套接字針對的傳輸層協議劃。
Socket 套接字,是由系統提供用于網絡通信的技術,是基于 TCP/IP 協議的網絡通信的基本操作單元。基 于Socket 套接字的網絡程序開發就是網絡編程
1.1TCP的特點
1.有連接2.可靠傳輸3.面向字節流4.有接收緩沖區,也有發送緩沖區5.大小不限
?1.2UDP的特點
數據報套接字:使用傳輸層UDP協議
以下為UDP的特點
1.無連接2.不可靠傳輸3.面向數據報4.有接收緩沖區,無發送緩沖區5.大小受限:一次最多傳輸 64k
?1.3區別
(1)有/無 連接
網絡中談到的連接,本質上是通信雙方各自保存雙方信息。
有連接是通信雙方都要同意。如:微信發電話。
無連接是收方無論是否同意,都會收到信息。如:微信發消息。
(2)可/不可 靠傳輸
由于網絡上存在的異常情況非常的多,無法保證網絡數據100%通信成功。
可靠傳輸 是指發送方知道自己發送的信息是否成功送達。反之不知道則是不可靠傳輸
(3)?面向數據報/字節流
指的是網絡中傳輸的基本單位是數據報/字節流。
2.UDP Socket的api的介紹
2.1DatagramSocket API
DatagramSocket 是UDP Socket,用于發送和接收UDP數據報。
socket 文件抽象了“網卡”這樣的硬件設備。
?(2)DatagramSocket 方法:
2.2DatagramPacket API ?
DatagramPacket是UDP Socket發送和接收的數據報。?
?(2)DatagramPacket 方法:
構造UDP發送的數據報時,需要傳入 SocketAddress ,該對象可以使用 InetSocketAddress 來創建。

3.回顯客戶端與服務器
什么叫回顯客戶端與與服務器呢?
其實就是:客戶端向服務端發送請求,一般來說我們的服務端會對我們發送的請求進行處理,我們這里為了簡單,就省略里面的處理過程,只實現將請求重新發回客戶端,不做任何處理。
3.1回顯服務器
3.1.1UdpEchoServer類的創建
1.需要創建一個DatagramSocket對象,因為需要操作網卡。
代碼:
public class UdpEchoServer {private DatagramSocket socket=null;public UdpEchoServer(int port) throws SocketException {socket=new DatagramSocket(port);}
}
代碼說明:
(1)socket=new DatagramSocket(port);
在運行一個服務器的時候,通常會手動指定一個端口號。
補:一個主機上的端口號,只能被一個進程綁定,但一個進程可以綁定多個端口號。?
(2)throws SocketException
通常表示socket創建失敗。
比如:端口號已經被別的進程占用了。
3.1.2服務器的運行方法start()
工作內容:
1. 讀取請求并解析
2. 根據請求計算響應 (對于 回顯服務器來說, 這一步啥都不用做)
3. 把響應返回到客戶端.
4.打印日志
?代碼:
import java.io.IOException;
import java.net.*;public class UdpEchoServer {private DatagramSocket socket = null;public UdpEchoServer(int port) throws SocketException {socket = new DatagramSocket(port);}public void start() throws IOException {System.out.println("服務器啟動");while (true) {DatagramPacket requestpacket = new DatagramPacket(new byte[4096], 4096);socket.receive(requestpacket);String request = new String(requestpacket.getData(), 0, requestpacket.getLength());String response = process(request);DatagramPacket responsepacket = new DatagramPacket(response.getBytes(), response.getBytes().length, requestpacket.getSocketAddress());socket.send(responsepacket);// 打印日志System.out.printf("[%s:%d] req: %s, resp: %s\n", requestpacket.getAddress().toString(),requestpacket.getPort(), request, response);}}private String process(String request) {return request;}
}
代碼說明:
1.? while (true) {~~~}
對于服務器來說,需要不停的收到請求,返回響應,收到請求,返回響應
2.? ??DatagramPacket requestpacket = new DatagramPacket(new byte[4096], 4096);
(1)byte[4096]->4096 表示的是載荷長度。
這個數組存的是消息正文(應用層數據包)也就是UDP數據包載荷部分。
(2)?socket.receive(requestpacket);
如果執行到socket.receive(requestpacket)的時候,還沒有客戶端發來請求,則會先堵塞等待。
(3 )requestpacket.getSocketAddress()
由于requestpacket是從客戶端來的數據報,故得到的InetAddress對象就會包含了客戶端的IP和端口號。
3.1.3main部分
代碼:
public static void main(String[] args) throws IOException {UdpEchoServer server = new UdpEchoServer(9090);server.start();}
代碼說明:
UdpEchoServer server = new UdpEchoServer(9090);
9090->這個端口號可以指定任何你想要指定的端口號。
?3.1.4.完整代碼
代碼:
package network;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;public class UdpEchoServer {private DatagramSocket socket = null;public UdpEchoServer(int port) throws SocketException {socket = new DatagramSocket(port);}// 服務器的啟動邏輯.public void start() throws IOException {System.out.println("服務器啟動!");while (true) {// 每次循環, 就是處理一個請求-響應過程.// 1. 讀取請求并解析DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);socket.receive(requestPacket);// 讀到的字節數組, 轉成 String 方便后續的邏輯處理.String request = new String(requestPacket.getData(), 0, requestPacket.getLength());// 2. 根據請求計算響應 (對于 回顯服務器來說, 這一步啥都不用做)String response = process(request);// 3. 把響應返回到客戶端.// 構造一個 DatagramPacket 作為響應對象DatagramPacket responsePacket = new DatagramPacket(response.getBytes(), response.getBytes().length,requestPacket.getSocketAddress());socket.send(responsePacket);// 打印日志System.out.printf("[%s:%d] req: %s, resp: %s\n", requestPacket.getAddress().toString(),requestPacket.getPort(), request, response);}}public String process(String request) {return request;}public static void main(String[] args) throws IOException {UdpEchoServer server = new UdpEchoServer(9090);server.start();}
}
?3.2回顯客戶端
3.2.1UdpEchoClient類的創建
代碼:
import java.io.IOException;
import java.net.*;
import java.util.Scanner;public class UdpEchoClient {private DatagramSocket socket = null;private String serverIp;private int serverPort;public UdpEchoClient(String serverIp,int serverPort) throws SocketException {this.socket = new DatagramSocket();this.serverIp = serverIp;this.serverPort = serverPort;}
}
?代碼說明:
(1)this.socket = new DatagramSocket();
客戶端這邊一般不會手動指定端口好,會讓系統自動分配一個端口號。
(2)private String serverIp;
? ? ? ? ?private int serverPort;?
? 客戶端需要主動給服務器發送請求,發送請求的前提是知道服務器在哪。
?3.2.2客戶端的運行方法start()
工作內容:
1. 從控制臺讀取要發送的請求數據.
2. 構造請求并發送
3. 讀取服務器的響應.
4. 把響應顯示到控制臺上
代碼:
public void start() throws IOException {System.out.println("客戶端啟動");Scanner scanner = new Scanner(System.in);while (true){System.out.print("->");if(!scanner.hasNext()){break;}String request=scanner.next();DatagramPacket requestpacket=new DatagramPacket(request.getBytes(),request.getBytes().length, InetAddress.getByName(serverIp),serverPort);socket.send(requestpacket);DatagramPacket responsepacket=new DatagramPacket(new byte[4096],4096);socket.receive(responsepacket);String response=new String(responsepacket.getData(),0,responsepacket.getLength());System.out.println(response);}}
??代碼說明:
InetAddress.getByName(serverIp)
把數據的單位從字符->字節。
3.2.3main部分?
代碼:
public static void main(String[] args) throws IOException {UdpEchoClient client = new UdpEchoClient("127.0.0.1", 9090);client.start();}
3.2.4?完整代碼
代碼:
import java.io.IOException;
import java.net.*;
import java.util.Scanner;public class UdpEchoClient {private DatagramSocket socket = null;private String serverIp;private int serverPort;// 此處 ip 使用的字符串, 點分十進制風格. "192.168.2.100"public UdpEchoClient(String serverIp, int serverPort) throws SocketException {this.serverIp = serverIp;this.serverPort = serverPort;socket = new DatagramSocket();}public void start() throws IOException {System.out.println("客戶端啟動");Scanner scanner = new Scanner(System.in);while (true) {// 要做四個事情System.out.print("-> "); // 表示提示用戶接下來要輸入內容.// 1. 從控制臺讀取要發送的請求數據.if (!scanner.hasNext()) {break;}String request = scanner.next();// 2. 構造請求并發送.DatagramPacket requestPacket = new DatagramPacket(request.getBytes(), request.getBytes().length,InetAddress.getByName(serverIp), serverPort);socket.send(requestPacket);// 3. 讀取服務器的響應.DatagramPacket responsePacket = new DatagramPacket(new byte[4096], 4096);socket.receive(responsePacket);// 4. 把響應顯示到控制臺上.String response = new String(responsePacket.getData(), 0, responsePacket.getLength());System.out.println(response);}}public static void main(String[] args) throws IOException {UdpEchoClient client = new UdpEchoClient("127.0.0.1", 9090);// UdpEchoClient client = new UdpEchoClient("139.155.74.81", 9090);client.start();}
}
運行結果:
?
小結?:
以上為我個人的小分享,如有問題,歡迎討論!!!?
都看到這了,不如關注一下,給個免費的贊?