Frame、TextArea、TextField)及事件監聽(ActionListener、WindowAdapter)。DataOutputStream、輸入流 DataInputStream、阻塞特性)。package chat.chat;
import java.awt.*;
import java.awt.event.*;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
public class ChatClient extends Frame {
private TextField tfTxt = new TextField(); // 輸入框
private TextArea taContent = new TextArea(); // 顯示區
private Socket socket;
private DataOutputStream dos;
public static void main(String[] args) {
new ChatClient().launchFrame();
}
public void launchFrame() {
setLocation(300, 200);
setSize(400, 300);
add(tfTxt, BorderLayout.SOUTH);
add(taContent, BorderLayout.CENTER);
pack();
// 關閉窗口事件
addWindowListener(new WindowAdapter() {
@Override public void windowClosing(WindowEvent e) {
disconnect();
System.exit(0);
}
});
// 回車發送消息
tfTxt.addActionListener(e -> {
String msg = tfTxt.getText().trim();
if (!msg.isEmpty()) {
taContent.append("我: " + msg + "\n");
tfTxt.setText("");
sendMessage(msg);
}
});
setVisible(true);
connect();
}
private void connect() {
try {
socket = new Socket("127.0.0.1", 8888);
dos = new DataOutputStream(socket.getOutputStream());
taContent.append("系統: 已連接服務器\n");
} catch (Exception e) {
taContent.append("系統: 連接失敗 - " + e.getMessage() + "\n");
e.printStackTrace();
}
}
private void sendMessage(String text) {
try {
dos.writeUTF(text);
dos.flush();
} catch (IOException e) {
taContent.append("系統: 發送失敗\n");
e.printStackTrace();
}
}
private void disconnect() {
try {
if (dos != null) dos.close();
if (socket != null) socket.close();
} catch (IOException e) { e.printStackTrace(); }
}
}
package chat.chat;
import java.io.*;
import java.net.*;
public class ChatServer {
public static void main(String[] args) {
ServerSocket ss = null;
Socket socket = null;
DataInputStream dis = null;
boolean running = true;
try {
ss = new ServerSocket(8888);
System.out.println("服務器啟動,端口 8888...");
} catch (BindException e) {
System.err.println("端口被佔用"); System.exit(1);
} catch (IOException e) { e.printStackTrace(); }
try {
while (running) {
socket = ss.accept(); // 阻塞等待連接
System.out.println("客戶端連接: " + socket.getInetAddress());
dis = new DataInputStream(socket.getInputStream());
while (running) {
String msg = dis.readUTF(); // 阻塞讀取
System.out.println("收到: " + msg);
// TODO: 此處應轉發給所有客戶端(下一版實現)
}
}
} catch (EOFException e) {
System.out.println("客戶端斷開");
} catch (IOException e) { e.printStackTrace(); }
finally {
closeQuietly(dis, socket, ss);
}
}
private static void closeQuietly(Closeable... resources) {
for (Closeable r : resources) {
if (r != null) try { r.close(); } catch (IOException ignored) {}
}
}
}
ChatServer.main,控制台顯示「服務器啟動」。ChatClient.main,彈出窗口,底部輸入框敲字按回車。accept() 後進入內層 while 循環讀取單客戶端消息,導致主循環無法再次 accept() → 不支持多客戶端並發。引入線程池或每連接一線程模型,服務端維護 List<DataOutputStream> 實現廣播;客戶端啟動獨立讀取線程 new Thread(() -> { while(true) ta.append(dis.readUTF()); }).start() 實現雙向通信。