オブジェクト送受信

先ほどのプログラムでは、サーバ・クライアント間の通信をテキストでおこなっていました。 今度は、より複雑なデータを交互に交換できるようにオブジェクトをSerialize で送ってみましょう。 Object の送受信ができれば、様々な情報を構造を保ったまま簡単に送れるはずですよね。

まずは接続に関して、サーバプログラムをみてみましょう。

ServerSocket serverSocket = new ServerSocket(portNum);		
System.out.println("Server waitting on serverSocket " + serverSocket);
Socket socket = serverSocket.accept(); /* 接続待ち */
System.out.println("Connection established");	/* 接続完了 */
/* ObjectStreamの場合、 out から先に作ってください */
ObjectOutputStream out = 
	new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = 
	new ObjectInputStream(socket.getInputStream());
try {
	receiveAndSend(in, out);
} finally {
	socket.close();
	serverSocket.close();
}

先ほどと大した差はなくて、入出力に ObjectInput/OutputStreamを作っている点だけが違いますね。 注意事項ですが、ObjectInputStream の生成には、相手側の ObjectOutputStream の生成が先に行われる必要があります。out から先に作るか、互違いになるようにしましょう。

送受信部分は、こんな感じ。前回との違いは、

  • 一行単位ではなく、オブジェクト単位で読み書きすること

ぐらいです。

while(true) {
	ObjMessage recvMsg = (ObjMessage) in.readObject();
	System.out.println("Client msg: " + recvMsg);
	if(recvMsg.toFinish) break;

	System.out.print("Server Input> "); System.out.flush();
	String userInput = userIn.nextLine();
	ObjMessage sendMsg =
		new ObjMessage(userInput,
				new Date(),
				randomeMaker.nextDouble(),
				userInput.equals("exit"));
	System.out.println("Server will send msg: " + sendMsg);
	out.writeObject(sendMsg);
	out.flush(); out.reset();
	if(sendMsg.toFinish) break;

}
System.out.println("normal termination");

一点注意事項があります。Object Serialization は、一度送ったオブジェクトを覚えています。なので、オブジェクトの状態を変えてから再度送信しても、「前に送った奴ね」といって、送信してくれません(前に送ったオブジェクトへの参照を渡す)。ObjectOutputStream#reset()メソッドを呼ぶと、オブジェクトの状態を忘れてくれます。これで、同じオブジェクトでも再送可能となります。