【Java 网络编程】TCP 服务器端 客户端 简单示例
文章目錄
- I IntelliJ IDEA 創建 Java 項目
- II 客戶端 Socket 創建
- III Socket 客戶端連接服務器端
- IV Socket 兩個端點信息獲取
- V 控制臺人機交互
- VI Socket 客戶端與服務器端交互
- VII ServerSocket 服務器端端口監聽
- VIII ServerSocket 服務器端參數獲取
- IX ServerSocket 服務器端同時與多個客戶端交互方案
- X Socket 客戶端代碼示例
- XI Socket 服務器端代碼示例
- XII 運行客戶端與服務器端代碼
I IntelliJ IDEA 創建 Java 項目
Java 程序使用 IntelliJ IDEA 進行開發 ;
創建客戶端項目 :
-
① 菜單欄 File -> New Project , 彈出 New Project 對話框 , 選擇 Gradle 類型下的 java 項目 ;
-
② 輸入 GroupId 和 項目名稱 , 一直點擊下一步到結束 , 最后一個對話框注意選擇項目所在位置 ;
II 客戶端 Socket 創建
創建 Socket 需要設置超時時長 , 要連接的服務器端的端點信息 , 該端點包括 IP 地址和端口號 ;
//1. 創建 Socket 對象Socket socket = new Socket();//2. 設置 Socket 的超時時間socket.setSoTimeout(5000);//3. 創建連接的端點 , 該端點包括 IP 地址和端口號InetSocketAddress inetSocketAddress =new InetSocketAddress(Inet4Address.getLocalHost(), //本機IP地址8000 //端口號);III Socket 客戶端連接服務器端
調用 Socket 對象的 connect 方法 , 即可發起對服務器的連接 , 如果連接成功 , 則會繼續執行 , 如果連接失敗或者超時 , 會拋出異常 ;
//4.. 連接服務器端點 , 并設置超時時間socket.connect(inetSocketAddress, 5000);IV Socket 兩個端點信息獲取
1. 獲取服務器端點的 IP 地址和端口號 : 調用 Socket 對象的 getInetAddress 方法獲取服務器端 IP 地址 , 調用 getPort 方法獲取服務器端的端口號 ;
//1. 獲取服務器 IP 地址InetAddress serverAddress = socket.getInetAddress();//2. 獲取服務器端口號int serverPort = socket.getPort();2. 獲取客戶端端點的 IP 地址和端口號 : 調用 Socket 對象的 getLocalAddress 方法 , 可以獲取客戶端的 IP 地址 , 調用 getLocalPort 方法可以獲取客戶端的端口號 ;
//3. 獲取客戶端 IP 地址InetAddress clientAddress = socket.getLocalAddress();//4. 獲取客戶端端口號int clientPort = socket.getLocalPort();V 控制臺人機交互
客戶端信息獲取 ( 人機交互 ) : 控制臺中等待用戶輸入 , BufferedReader 的 readLine 方法 , 可以在控制臺中阻塞等待用戶輸入 , 用戶可以在控制臺輸入信息 , 然后客戶端將該信息傳給服務器 ; 下面是鍵盤輸入流的創建和使用過程
//1. 獲取控制臺輸入流InputStream is = System.in;//2. 該輸入流會阻塞 , 等待用戶控制臺輸入BufferedReader br = new BufferedReader(new InputStreamReader(is));//4. 阻塞命令行 , 等待用戶輸入一行數據, 并存入 string 對象中String string = br.readLine();VI Socket 客戶端與服務器端交互
服務器 -> 客戶端 : 客戶端阻塞等待服務器端發送數據 , 從 Socket 中獲取 BufferedReader 輸入流 , 根據輸入流創建 BufferedReader , 調用 readLine 方法阻塞等待服務器傳回信息 ;
//1. 獲取服務器端輸入流cisFromServer = socket.getInputStream();//2. 將輸入流轉為 BufferedReaderBufferedReader brFromServer = new BufferedReader(new InputStreamReader(isFromServer));//6. 阻塞控制臺 , 從服務器讀取一行數據String stringFromServer = brFromServer.readLine();客戶端 -> 服務器 : 從 Socket 中獲取輸出流 OutputStream , 根據該輸出流創建 PrintStream , 可以將字符串輸出到客戶端 ;
//4. 獲取客戶端的輸出流 , 用于向服務器端寫出數據OutputStream os = socket.getOutputStream();//5. 創建打印流 , 用于向服務器端寫出字符PrintStream ps = new PrintStream(os);//5. 通過打印流 , 將該字符串傳輸給服務器端ps.println(string);VII ServerSocket 服務器端端口監聽
創建 ServerSocket 對象 , 只需要指定端口即可 , 不需要指定 IP 地址 , 其 IP 地址就是本機的 IP 地址 , 如果機器有多個 IP 地址 , 如果沒有指定 IP 地址 , 那么會監聽所有的 IP 地址的指定端口號 ;
//1. 創建服務器套接字 , 只需要指定端口即可 , 不需要指定 IP 地址// 其 IP 地址就是本機的 IP 地址 , 如果機器有多個 IP 地址// 如果沒有指定 IP 地址 , 那么會監聽所有的 IP 地址的指定端口號ServerSocket serverSocket = new ServerSocket(8000);VIII ServerSocket 服務器端參數獲取
調用 ServerSocket 對象的 getInetAddress 獲取服務器端的 IP 地址 , 調用該對象的 getLocalPort 可以獲取服務器端監聽的端口號 ;
//2. 獲取服務器端 IP 地址InetAddress inetAddress = serverSocket.getInetAddress();//3. 獲取服務器端口號int localPort = serverSocket.getLocalPort();IX ServerSocket 服務器端同時與多個客戶端交互方案
將與單個客戶端交互的操作封裝到線程中 , 每當與一個新的客戶端建立連接 , 就開啟一個異步線程處理與該客戶端之間的交互 ;
客戶端處理線程 :
/*** 異步線程 , 處理單個客戶端連接* 如果多個客戶端連接 , 就需要創建多個該類, 同時處理多個客戶端連接*/public static class ClientHandler extends Thread{//1. 客戶端 Socket 連接private Socket clientSocket;public ClientHandler(Socket clientSocket) {this.clientSocket = clientSocket;}}無限循環等待客戶端連接 , 一旦連接成功 , 就開啟一個異步線程 ;
//II. 等待客戶端連接, 注意此處是無限循環連接while(true){//1. 收到一個客戶端連接請求 , 獲取 客戶端 Socket 連接Socket clientSocket = serverSocket.accept();//2. 將 Socket 連接傳入 ClientHandler 線程 , 異步處理與客戶端交互操作ClientHandler clientHandler = new ClientHandler(clientSocket);//3. 啟動 與客戶端 Socket 交互處理 異步線程clientHandler.start();}X Socket 客戶端代碼示例
import java.io.*; import java.net.*;/*** 客戶端*/ public class Client {/*** 客戶端入口函數* @param args*/public static void main(String[] args){try {//I. 連接//1. 創建 Socket 對象Socket socket = new Socket();//2. 設置 Socket 的超時時間socket.setSoTimeout(5000);//3. 創建連接的端點 , 該端點包括 IP 地址和端口號InetSocketAddress inetSocketAddress =new InetSocketAddress(Inet4Address.getLocalHost(), //本機IP地址8000 //端口號);//4.. 連接服務器端點 , 并設置超時時間socket.connect(inetSocketAddress, 5000);//5. 如果連接成功會繼續執行下面的操作, 如果失敗會根據失敗情況拋出異常//II. 獲取 Socket 連接兩個端點的屬性, IP 地址和端口號//1. 獲取服務器 IP 地址InetAddress serverAddress = socket.getInetAddress();//2. 獲取服務器端口號int serverPort = socket.getPort();//3. 獲取客戶端 IP 地址InetAddress clientAddress = socket.getLocalAddress();//4. 獲取客戶端端口號int clientPort = socket.getLocalPort();System.out.println("服務器連接成功\n服務器地址 : " + serverAddress +" , 服務器端口號 : " + serverAddress +"\n客戶端地址 : " + clientAddress + " , 客戶端端口號 : " + clientPort);//向服務器端發送數據sendToServer(socket);//III. 關閉 Socket 連接socket.close();System.out.println("客戶端 Socket 連接關閉");} catch (SocketException e) {e.printStackTrace();} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {//客戶端可能掛了 , 需要重啟}}public static void sendToServer(Socket socket){try {//I. 獲取用戶控制臺輸入信息//1. 獲取控制臺輸入流InputStream is = System.in;//2. 該輸入流會阻塞 , 等待用戶控制臺輸入BufferedReader br = new BufferedReader(new InputStreamReader(is));//II. 將用戶輸入信息上傳到服務器//4. 獲取客戶端的輸出流 , 用于向服務器端寫出數據OutputStream os = socket.getOutputStream();//5. 創建打印流 , 用于向服務器端寫出字符PrintStream ps = new PrintStream(os);//III. 從服務器獲取信息 , 這里循環讀取數據, 接收到 服務器端的 quit 字符串才退出//1. 獲取服務器端輸入流InputStream isFromServer = socket.getInputStream();//2. 將輸入流轉為 BufferedReaderBufferedReader brFromServer = new BufferedReader(new InputStreamReader(isFromServer));//3. 循環控制變量 , 退出時設置為 falseboolean isReadFromServer = true;while (isReadFromServer){//4. 阻塞命令行 , 等待用戶輸入一行數據, 并存入 string 對象中String string = br.readLine();//5. 通過打印流 , 將該字符串傳輸給服務器端ps.println(string);//6. 阻塞控制臺 , 從服務器讀取一行數據String stringFromServer = brFromServer.readLine();//7. 根據服務器返回的數據進行不同操作if("quit".equals(stringFromServer)){//停止循環isReadFromServer = false;}else{System.out.println(stringFromServer);}}//IV. 釋放資源br.close();ps.close();brFromServer.close();} catch (IOException e) {e.printStackTrace();}} }
XI Socket 服務器端代碼示例
import java.io.*; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket;/*** 服務器端*/ public class Server {/*** 服務器端入口函數* @param args*/public static void main(String[] args){try {//I. 創建服務器套接字, 并監聽端口//1. 創建服務器套接字 , 只需要指定端口即可 , 不需要指定 IP 地址// 其 IP 地址就是本機的 IP 地址 , 如果機器有多個 IP 地址// 如果沒有指定 IP 地址 , 那么會監聽所有的 IP 地址的指定端口號ServerSocket serverSocket = new ServerSocket(8000);//2. 獲取服務器端 IP 地址InetAddress inetAddress = serverSocket.getInetAddress();//3. 獲取服務器端口號int localPort = serverSocket.getLocalPort();System.out.println("服務器開啟\nIP 地址 : " + inetAddress + " , 端口號 : " + localPort);//II. 等待客戶端連接, 注意此處是無限循環連接while(true){//1. 收到一個客戶端連接請求 , 獲取 客戶端 Socket 連接Socket clientSocket = serverSocket.accept();//2. 將 Socket 連接傳入 ClientHandler 線程 , 異步處理與客戶端交互操作ClientHandler clientHandler = new ClientHandler(clientSocket);//3. 啟動 與客戶端 Socket 交互處理 異步線程clientHandler.start();}} catch (IOException e) {e.printStackTrace();}}/*** 異步線程 , 處理單個客戶端連接* 如果多個客戶端連接 , 就需要創建多個該類, 同時處理多個客戶端連接*/public static class ClientHandler extends Thread{//1. 客戶端 Socket 連接private Socket clientSocket;//2. 循環控制變量private boolean loopFlag = true;public ClientHandler(Socket clientSocket) {this.clientSocket = clientSocket;}@Overridepublic void run() {super.run();//I. 獲取客戶端相關信息//1. 獲取客戶端的 IP 地址InetAddress inetAddress = clientSocket.getInetAddress();//2. 獲取客戶端的端口號int port = clientSocket.getPort();//3. 打印客戶端的信息System.out.println("客戶端信息 : \nIP 地址 : " + inetAddress + " , 端口號 : " + port);try {//II. 創建與客戶端交互的輸入輸出流//1. 獲取客戶端 Socket 輸出流 , 用于向客戶端發送數據OutputStream os = clientSocket.getOutputStream();//2. 創建打印流 , 用于向客戶端輸出數據PrintStream ps = new PrintStream(os);//3. 獲取客戶端 Socket 輸入流 , 用于接收客戶端數據InputStream is = clientSocket.getInputStream();//4. 獲取客戶端的字符輸入流 , 該輸入流可以阻塞等待客戶端輸入BufferedReader br = new BufferedReader(new InputStreamReader(is));//III. 循環處理與客戶端交互的信息while (loopFlag){//1. 等待客戶端輸入String string = br.readLine();//2. 處理客戶端輸入if("quit".equals(string)){//如果客戶端發送退出, 那么停止循環, 將該信息在送回客戶端loopFlag = false;//將信息發送到客戶端ps.println("quit");}else{//將信息打印到控制臺System.out.println(string);//將發送成功信息返回給客戶端ps.println("發送成功 , 大小 " + string.length() + " 字節");}}//IV. 關閉相關資源ps.close();br.close();} catch (IOException e) {e.printStackTrace();}finally {try {//如果出現異常 , 將該 Socket 關閉clientSocket.close();} catch (IOException e) {e.printStackTrace();}}System.out.println("客戶端退出 : \nIP 地址 : " + inetAddress + " , 端口號 : " + port);}}}
XII 運行客戶端與服務器端代碼
1. 編譯兩個 Java 代碼 : 選擇菜單欄 -> Build -> Rebuild Project 選項 , 獲取到 Client.class 和 Server.class 文件 ;
2. 字節碼文件地址 : 編譯后的 class 字節碼文件在工程目錄的 out\production\classes 目錄下 ;
打開兩個命令行界面 , 首先進入該目錄 , 先運行服務器端 , 在命令行中輸入 java Server , 即開啟了服務器端 ; 再打開客戶端 , 在另一個命令行中運行 java Client , 即開啟了客戶端 ;
客戶端輸入文字 , 與服務器端交互 :
總結
以上是生活随笔為你收集整理的【Java 网络编程】TCP 服务器端 客户端 简单示例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Java 网络编程】Socket TC
- 下一篇: 【Java 网络编程】网络相关概念