Java - 网络 - 最佳实践 - 混合同步/异步命令

时间:2011-06-04 21:20:28

标签: java sockets asynchronous synchronous

我正在用Java开发一个小型客户端服务器程序。

客户端和服务器通过一个tcp连接进行连接。通信的大多数部分是异步的(可以在任何时间发生),但是我希望某些部分是同步的(比如发送命令的ACK)。

我使用一个Thread从套接字的InputStream读取命令并引发onCommand()事件。命令本身由Command-Design-Pattern推进。

什么是最佳实践方法(Java),以便能够在不丢失可能同时出现的其他命令的情况下等待ACK?

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

EDIT1

将其想象为FTP连接,但数据和控制命令都在同一个连接上。我想捕获对control-command的响应,而后台的数据流正在运行。

EDIT2

所有内容都以块的形式发送,以通过同一TCP连接启用多个(不同的)传输(多路复用)

Block:
1 byte - block's type
2 byte - block's payload length
n byte - block's paylod

2 个答案:

答案 0 :(得分:4)

原则上,您需要一个被阻止线程的注册表(或者更好的是,它们正在等待的锁定),并使用一些标识符进行锁定,这些标识符将由远程端发送。

对于异步操作,您只需发送消息并继续。

对于同步操作,在发送消息之后,您的发送线程(或发起此消息的线程)创建一个锁定对象,将一些密钥添加到注册表中,然后等待锁定,直到得到通知。

读取线程在收到一些答案时,会在注册表中查找锁定对象,添加答案并调用notify()。然后它会读取下一个输入。

这里的艰苦工作是正确的同步以避免死锁以及错过通知(因为它在我们将自己添加到注册表之前回来了)。

当我为Fencing - applet实现远程方法调用协议时,我做了类似的事情。原则上,RMI的工作方式相同,只是没有异步消息。

答案 1 :(得分:1)

@ Paulo的解决方案是我之前使用的解决方案。但是,可能有一个更简单的解决方案。

假设您没有后台线程在连接中读取结果。你可以做的是使用当前线程来读取任何结果。

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

// Synchronous call.
conn.sendMessage("Sync-request");
String reply = conn.readMessage();