首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Socket 通信實戰:基於 DOS 命令行的私聊/群聊雙模式實現

     編輯:Java 綜合教學

架構設計

  • Server:單線程接受連接,為每客戶端啟動線程,維護 Vector<Socket> 在線列表
  • Client:雙線程模型(ClientSend 發送 / ClientReceive 接收)
  • 協議約定:@IP:PORT 內容 為私聊,其餘為群聊

服務端核心邏輯

public class Server extends Thread {
    private static Vector<Socket> clients = new Vector<>();
    private Socket clientSocket;
    private BufferedReader in;
    private PrintWriter out;

    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(2014);
        System.out.println("服務器啟動!");
        while (true) {
            new Server(server.accept()).start();
        }
    }

    public Server(Socket socket) {
        this.clientSocket = socket;
        clients.add(socket);
        // 初始化流...
    }

    @Override
    public void run() {
        try {
            welcomeNewClient();  // 歡迎語 + 廣播上線通知
            while (true) {
                String msg = in.readLine();
                if ("bye".equals(msg) || "拜拜".equals(msg)) {
                    offline(); break;
                } else if (msg.startsWith("@") && msg.indexOf(' ') > 0) {
                    privateChat(msg);  // @IP:PORT 內容
                } else {
                    broadcast(msg);    // 群聊
                }
            }
        } catch (IOException e) { /* 忽略 */ }
    }

    private void privateChat(String msg) {
        int end = msg.indexOf(' ');
        String targetAddr = msg.substring(1, end);
        for (Socket s : clients) {
            String addr = s.getInetAddress().toString().replace("/", "") + ":" + s.getPort();
            if (targetAddr.equals(addr)) {
                String sender = clientSocket.getInetAddress().toString().replace("/", "") 
                              + ":" + clientSocket.getPort();
                new PrintWriter(s.getOutputStream(), true)
                    .println("大神" + sender + " 對你 說: " + msg.substring(end));
                break;
            }
        }
    }
    // broadcast(), welcomeNewClient(), offline() 類似...
}

客戶端雙線程模型

// 發送線程
class ClientSend extends Thread {
    private PrintWriter out;
    public void run() {
        Scanner sc = new Scanner(System.in);
        String msg = sc.nextLine();
        while (true) {
            if ("bye".equals(msg) || "拜拜".equals(msg)) { out.println(msg); break; }
            out.println(msg);
            msg = sc.nextLine();
        }
    }
}

// 接收線程
class ClientReceive extends Thread {
    private BufferedReader in;
    public void run() {
        try {
            String msg = in.readLine();
            while (!"bye".equals(msg)) {
                System.out.println(msg);
                msg = in.readLine();
            }
        } catch (IOException e) { e.printStackTrace(); }
    }
}

運行測試

  1. 啟動 Server
  2. 多個終端啟動 Client
  3. 群聊:直接輸入文字
  4. 私聊:@127.0.0.1:12345 你好(@ 後必須有空格)

代碼亮點與不足

亮點不足
Vector 線程安全存儲連接無心跳檢測,死連接不清理
PrintWriter autoFlush 簡化發送私聊協議簡陋,無錯誤碼
雙線程模型職責清晰無消息序列化,僅支援文本

完整代碼見:GitHub 項目

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved