Java基礎之Socket通信簡單實例


  前言

  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通信簡單實例暫時先記錄到這,后續再進行補充


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM