Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - networking - Best Practice - mixed synchronous / asynchronous commands

I'm developing a small client-server program in Java.

The client and the server are connected over one tcp-connection. Most parts of the communication are asynchronous (can happen at any time) but some parts I want to be synchronous (like ACKs for a sent command).

I use a Thread that reads commands from the socket's InputStream and raises an onCommand() event. The Command itself is progressed by the Command-Design-Pattern.

What would be a best-practice approach (Java), to enable waiting for an ACK without missing other, commands that could appear at the same time?

con.sendPacket(new Packet("ABC"));
// wait for ABC_ACK

edit1

Think of it like an FTP-Connection but that both data and control-commands are on the same connection. I want to catch the response to a control-command, while data-flow in the background is running.

edit2

Everything is sent in blocks to enable multiple (different) transmissons over the same TCP-Connection (multiplexing)

Block:
1 byte - block's type
2 byte - block's payload length
n byte - block's paylod
like image 354
kazu Avatar asked Jun 04 '11 21:06

kazu


2 Answers

In principle, you need a registry of blocked threads (or better, the locks on which they are waiting), keyed with some identifier which will be sent by the remote side.

For asynchronous operation, you simply sent the message and proceed.

For synchronous operation, after sending the message, your sending thread (or the thread which initiated this) create a lock object, adds this with some key to the registry and then waits on the lock until notified.

The reading thread, when it receives some answer, looks in the registry for the lock object, adds the answer to it, and calls notify(). Then it goes reading the next input.

The hard work here is the proper synchronization to avoid dead locks as well as missing a notification (because it comes back before we added ourself to the registry).

I did something like this when I implemented the remote method calling protocol for our Fencing-applet. In principle RMI works the same way, just without the asynchronous messages.

like image 171
Paŭlo Ebermann Avatar answered Oct 24 '22 04:10

Paŭlo Ebermann


@Paulo's solution is one I have used before. However, there may be a simpler solution.

Say you don't have a background thread reading results in the connection. What you can do instead do is use the current thread to read any results.

// Asynchronous call
conn.sendMessage("Async-request");
// server sends no reply.

// Synchronous call.
conn.sendMessage("Sync-request");
String reply = conn.readMessage();
like image 36
Peter Lawrey Avatar answered Oct 24 '22 06:10

Peter Lawrey