前言
Java網絡編程之Socket套接字,Socket套接字使用TCP提供了兩台計算機之間的通信機制
TCP(英語:Transmission Control Protocol,傳輸控制協議) 是一種面向連接的、可靠的、基於字節流的傳輸層通信協議,TCP 層是位於 IP 層之上,應用層之下的中間層。TCP 保障了兩個應用程序之間的可靠通信。通常用於互聯網協議,被稱 TCP / IP
本文記錄Java的Socket通信簡單實例
服務端
package cn.huanzi.qch.util; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; import java.nio.charset.StandardCharsets; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Socket服務端 */ public class SocketServer { public static void main(String[] args) throws Exception{ //服務端在20006端口監聽客戶端請求的TCP連接 ServerSocket server = new ServerSocket(20086); Socket client; System.out.println("服務端啟動成功!"); //如果使用多線程,那就需要線程池,防止並發過高時創建過多線程耗盡資源 ExecutorService threadPool = Executors.newFixedThreadPool(10); while (true) { //等待客戶端的連接,如果沒有獲取連接 client = server.accept(); //為每個客戶端連接開啟一個線程 threadPool.submit(new ServerThread(client)); } } } /** * 與客戶端連接操作異步線程 */ class ServerThread implements Runnable { //socket連接 private final Socket client; public ServerThread(Socket client){ this.client = client; } @Override public void run() { try{ System.out.println("與客戶端["+client.getInetAddress()+":"+client.getPort()+"]連接成功!"); //獲取Socket的輸出流,用來向客戶端發送數據 PrintStream out = new PrintStream(client.getOutputStream()); //獲取Socket的輸入流,用來接收從客戶端發送過來的數據 BufferedReader buf = new BufferedReader(new InputStreamReader(client.getInputStream(), StandardCharsets.UTF_8)); boolean flag =true; while(flag){ //接收從客戶端發送過來的數據 String msg = buf.readLine(); //約定:通過約定符號'exit'通知服務端關閉與客戶端的連接 if("exit".equals(msg)){ flag = false; }else{ //將接收到的字符串前面加上echo,發送到對應的客戶端 out.println("echo:"+msg); } System.out.println("收到客戶端["+client.getInetAddress()+":"+client.getPort()+"]消息:"+msg); } System.out.println("與客戶端["+client.getInetAddress()+":"+client.getPort()+"]斷開連接..."); out.close(); buf.close(); client.close(); }catch(Exception e){ System.err.println("Socket連接異常..."); e.printStackTrace(); } } }
客戶端
package cn.huanzi.qch.util; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket; import java.net.SocketTimeoutException; import java.nio.charset.StandardCharsets; /** * Socket客戶端 */ public class SocketClient { //地址 private static final String host = "127.0.0.1"; //端口 private static final int port = 20086; //Socket連接 private static Socket client; //Socket的輸出流,用來發送數據到服務端 private static PrintStream out; //Socket的輸入流,用來接收從服務端發送過來的數據 private static BufferedReader buf; /** * 初始化Socket連接 */ private static void init() throws IOException { //客戶端請求與 host 在 port 端口建立TCP連接 client = new Socket(host, port); //獲取Socket的輸出流 out = new PrintStream(client.getOutputStream()); //獲取Socket的輸入流 buf = new BufferedReader(new InputStreamReader(client.getInputStream(), StandardCharsets.UTF_8)); } /** * 發送消息 */ private static void sendMsg(String msg) throws IOException { try{ //發送數據到服務端 out.println(msg); }catch (Exception e){ //打印日志,並重連Socket System.err.println("Socket連接異常,正在重新連接..."); e.printStackTrace(); init(); //重新發送數據數據到服務端 out.println(msg); } //等待服務端響應 try{ String echo = buf.readLine(); System.out.println("收到服務端回應:"+echo); }catch(SocketTimeoutException e){ System.err.println("服務端響應超時..."); e.printStackTrace(); } catch (IOException e) { System.err.println("服務端響應異常..."); e.printStackTrace(); } } /** * 關閉Socket連接 * 約定:通過約定符號'exit'通知服務端關閉與客戶端的連接 */ private static void close() throws IOException { //通知服務端結束與客戶端的連接異步線程 out.println("exit"); out.close(); buf.close(); client.close(); } public static void main(String[] args) throws IOException, InterruptedException { init(); for (int i = 1; i <= 5; i++) { sendMsg("你好,我是消息"+i); Thread.sleep(2000);//休眠 } close(); } }
效果
先運行服務端,再運行客戶端
客戶端
服務端
后記
為了減少傳輸數據的大小,可以通過約定報文格式,傳輸16進制數據,例如:OxFF 01 3A 4D
Java的Socket通信簡單實例暫時先記錄到這,后續再進行補充