現象:Client 端 `new ObjectInputStream(socket.getInputStream())` 卡住不動,Server 端對應行調整順序後就正常。根因是 **`ObjectInputStream` 建構子會阻塞等待對方寫入序列化標頭 (Stream Header)**。
// Client 端
Socket socket = new Socket("host", 8888);
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.flush(); // 關鍵:先推送標頭
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); // 此時不再阻塞
// Server 端
Socket socket = serverSocket.accept();
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.flush(); // 關鍵:先推送標頭
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); // 此時不再阻塞
// Client
try (Socket s = new Socket("host", 8888);
ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
FileInputStream fis = new FileInputStream(file)) {
oos.flush(); // 送標頭
oos.writeUTF(file.getName());
oos.writeLong(file.length());
byte[] buf = new byte[8192];
int len;
while ((len = fis.read(buf)) > 0) oos.write(buf, 0, len);
oos.flush();
String ack = ois.readUTF(); // 等待 "OK"
System.out.println(ack);
}
// Server
try (ServerSocket ss = new ServerSocket(8888);
Socket s = ss.accept();
ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
ObjectInputStream ois = new ObjectInputStream(s.getInputStream())) {
oos.flush(); // 送標頭
String name = ois.readUTF();
long len = ois.readLong();
try (FileOutputStream fos = new FileOutputStream(new File("recv/" + name))) {
byte[] buf = new byte[8192];
int read, total = 0;
while (total < len && (read = ois.read(buf)) > 0) {
fos.write(buf, 0, read);
total += read;
}
}
oos.writeUTF("OK");
oos.flush();
}
「雙向 ObjectStream,**雙方必須先 new OOS → flush() → 再 new OIS**,順序一致才不會互相等標頭卡死。」
記住這順序,Socket 序列化傳輸就不會再在建構子處莫名阻塞。