Java網絡編程主要有TCP(可靠流式)和UDP(數據報)兩種模式。TCP保證數據順序、無丟失,連接斷開雙向結束;UDP效率高但可能丟包、亂序。本文提供基於Swing界面的TCP Server/Client完整代碼。
package TCP;
import java.io.*; import java.net.*; import javax.swing.*;
public class Server {
static BufferedReader br; static PrintStream ps; static JTextArea text;
JFrame frame;
public Server() {
frame = new JFrame("服務器端");
text = new JTextArea(); text.setEditable(false);
frame.add(new JScrollPane(text));
frame.setSize(300,400); frame.setVisible(true);
}
public static void main(String[] args) throws Exception {
new Server();
ServerSocket server = new ServerSocket(2000);
text.append("監聽2000端口\n");
Socket client = server.accept(); // 阻塞等待連接
br = new BufferedReader(new InputStreamReader(client.getInputStream()));
ps = new PrintStream(client.getOutputStream());
String msg;
while ((msg = br.readLine()) != null) {
text.append("服務器端收到:" + msg + "\n");
ps.println(msg); // 回傳確認
if (msg.equals("quit")) {
text.append("客戶端已退出!\n服務器程序將退出!");
break;
}
}
ps.close(); br.close(); client.close();
}
}
package TCP;
import java.awt.*; import java.awt.event.*; import java.io.*; import javax.swing.*; import java.net.*;
public class Client implements ActionListener {
// 連接界面組件
JFrame frame; JTextField adresstext, porttext; JButton connect;
// 通信界面組件
JFrame frame1; JTextArea shurukuang; TextArea jieshoukuang; JButton send;
// 網絡流
static BufferedReader br1; static PrintStream ps; static BufferedReader br2;
static Socket client; static ByteArrayInputStream stringInputStream;
public Client() {
// 初始化連接界面
frame = new JFrame(); frame.setLayout(new FlowLayout());
adresstext = new JTextField("127.0.0.1",10);
porttext = new JTextField("2000",10);
connect = new JButton("連接"); connect.addActionListener(this);
frame.add(new JLabel("IP地址")); frame.add(adresstext);
frame.add(new JLabel("端口號")); frame.add(porttext); frame.add(connect);
frame.setSize(200,150); frame.setVisible(true);
// 初始化通信界面(初始隱藏)
frame1 = new JFrame(); frame1.setLayout(new FlowLayout());
shurukuang = new JTextArea("請輸入····",5,40);
jieshoukuang = new TextArea(8,60); jieshoukuang.setEditable(false);
send = new JButton("發送"); send.addActionListener(this);
frame1.add(new JLabel("請輸入")); frame1.add(shurukuang);
frame1.add(send);
frame1.add(new JLabel("已接受")); frame1.add(jieshoukuang);
frame1.setSize(500,350); frame1.setVisible(false);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == connect) {
try {
client = new Socket("127.0.0.1", 2000);
frame.setVisible(false); frame1.setVisible(true);
br1 = new BufferedReader(new InputStreamReader(client.getInputStream()));
ps = new PrintStream(client.getOutputStream());
jieshoukuang.append("已經連接上服務器!\n");
} catch (IOException ex) { ex.printStackTrace(); }
}
if (e.getSource() == send) {
try {
stringInputStream = new ByteArrayInputStream(shurukuang.getText().getBytes());
br2 = new BufferedReader(new InputStreamReader(stringInputStream));
String msg;
while ((msg = br2.readLine()) != null) {
ps.println(msg);
jieshoukuang.append("向服務器發送:" + msg + "\n");
jieshoukuang.append("客戶端接受響應:" + br1.readLine() + "\n");
if (msg.equals("quit")) { /* 關閉資源、隱藏窗口 */ break; }
}
shurukuang.setText("");
} catch (IOException ex) { ex.printStackTrace(); }
}
}
public static void main(String[] args) throws IOException {
new Client(); // 顯示連接界面
// 注意:這裡重複創建Socket會導致邏輯錯誤,實際應在connect事件中初始化流
}
}
readLine()返回字符串或null,需賦值給變量才能多次使用(如判斷null與打印)。main中提前創建client但未初始化流,事件中又創建新client,導致br1/ps引用混亂。正確做法:僅在連接成功後在事件處理器中初始化Socket及流,main僅啟動UI。代碼演示了TCP通信的基本流程,實際項目中應加入線程處理並發、異常恢復、協議設計等健壯性措施。