1:在java的服务端代码:
public class SimpleServerSocket { public static void main(String[] args) { try { ServerSocket server = new ServerSocket(6789); Socket client; while (true) { try { client = server.accept(); System.out.println(client.getInetAddress()); System.out.println("server waiting for getInputStream " + System.currentTimeMillis()); ObjectInputStream input = new ObjectInputStream(client.getInputStream()); System.out.println("server waiting for getOutputStream() " + System.currentTimeMillis()); ObjectOutputStream output = new ObjectOutputStream(client.getOutputStream()); System.out.println("server waiting for reading client " + System.currentTimeMillis()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } //client.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
2: 客户端的代码:
public class SimpleClientSocket { public static void main(String[] args) { Socket server; try { server = new Socket("127.0.0.1", 6789); /** * 下面这两行的顺序改变试试 */ ObjectInputStream input = new ObjectInputStream(server.getInputStream()); ObjectOutputStream output = new ObjectOutputStream(server.getOutputStream()); System.out.println(server.getInetAddress()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
可以试下再本机运行。如果client和server都是先进行
getInputStream
那 么程序运行的时候就会一直堵塞。不能成功建立通讯。
但是如果将client调换下顺序,就可以成功 建立连接。
目前猜想的原因是在TCP三次握手的时候堵塞住了吧,具体原因还不是很清楚,继续研究 中!~
=========================================================================
目 前原因已经找到,主要问题是出在
构造ObjectInputStream的时候出问题的 。看 下源码:
public ObjectInputStream(InputStream in) throws IOException {
verifySubclass();
bin = new BlockDataInputStream(in);
handles = new HandleTable(10);
vlist = new ValidationList();
enableOverride = false;
readStreamHeader();
bin.setBlockDataMode(true);
}
读取stream的header的时候,源码:
short s0 = bin.readShort();
这个方法会阻塞的,直 到读到东西位置!!
因此,如果客户端跟服务端都先构造ObjectInputStream的话,就 会互相堵塞,而如果其中一方先构造
ObjectOutputStream的时候就不会出问题,这是因为构造 ObjectOutputStream的时候会有一个方法,看源码:
public ObjectOutputStream(OutputStream out) throws IOException {
verifySubclass();
bout = new BlockDataOutputStream(out);
handles = new HandleTable(10, (float) 3.00);
subs = new ReplaceTable(10, (float) 3.00);
enableOverride = false;
writeStreamHeader();
bout.setBlockDataMode(true);
if (extendedDebugInfo) {
debugInfoStack = new DebugTraceInfoStack();
} else {
debugInfoStack = null;
}
}
wirte的源码:
protected void writeStreamHeader() throws IOException {
bout.writeShort(STREAM_MAGIC);
bout.writeShort(STREAM_VERSION);
}
这 里会写一个魔数和一个版本号,这样构造ObjectInputStream的时候就会读取到东西啦。
至此问题得以弄清楚!~