我正在编写一个 Android 聊天应用程序,现在我在组织服务器请求-响应方面遇到问题。
在我的聊天消息中,以 JSON 格式表示,其中包含 TransactionId 字段,该字段对于特定的一组请求-响应对来说是唯一的。例如,请求将消息设置为已读:
{Type : "READ_MESSAGE", Sender : "Alice", Recievier : "server", Body : "123456",
TransactionId : "550e8400-e29b-41d4-a716-446655440000"}
和相应的响应:
{Type : "READ_MESSAGE", Sender : "server", Recievier : "Alice", Body : "1", TransactionId : "550e8400-e29b-41d4-a716-446655440000"}
这里的 Id 用于识别哪个请求响应已到来,例如,当我等待 5 个不同的 READ_MESSAGE 响应时。
但是问题来了。我的 Android 客户端由一个接受传入消息的线程和每个传出消息的单独线程组成。因此,我迫不及待地等待传出消息线程中的响应,现在我使用以下代码:
private void sendJSON(final String JSON) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
runnable.out.println(JSON);
JSONMessage json = new JSONMessage(JSON);
//After 5 seconds we should check: was message sent successfully?
try {
Thread.sleep(5000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
sendMessageToUI(json.getTransactionId(), CHECK_IF_SENT);
}
});
t.start();
}
和
private void proceeIncoming() {
while (!SocketClient.this.toExit) {
try {
String str = SocketClient.this.in.readLine();
if (str != null) {
JSONMessage recievedMsg = new JSONMessage(str);
switch (recievedMsg.getType()) {
case MESSAGE:
SocketService.this.sendJSON(new JSONMessage.Builder(MessageType.RECEIVED_MESSAGE,
Global.getUserPref().getString("Username", ""),
"server",
recievedMsg.getTransactionId()).build().toString());
SocketService.this.sendMessageToUI(str, MSG_SEND_JSON_MESSAGE);
History.writeJSON(str);
break;
case RECEIVED_MESSAGE:
SocketService.this.sendMessageToUI(recievedMsg.getTransactionId(), SUCCESSFULLY_SENT_MESSAGE);
break;
case READ_MESSAGE:
SocketService.this.sendMessageToUI(recievedMsg.getTransactionId(), READ_MESSAGE);
break;
default:
break;
}
}
} catch (IOException e) {
Log.i(Global.LOG_TAG, "IOException");
reconnect(1000);
}
}
try {
SocketClient.this.in.close();
SocketClient.this.out.close();
SocketClient.this.socket.close();
} catch (IOException e) {
Log.e(Global.LOG_TAG, "Error closing client");
}
}
然后 UI 中的 Activity 处理该消息。它确实有效,但总体来说对我来说感觉就像是一个杂凑。
不仅非常令人困惑,我还必须将 TransactionId 存储在我的 Message 类中,以便能够使用此 Id 查找消息,这完全是错误的,并且因为此 Id 是由客户端创建的,所以我不能当然它是唯一的,所以通过这个 id 查询数据库可能会得到多个结果。
还有其他方法可以做到这一点吗?
最佳答案
我建议有 3 个线程:
- 一个用于主应用程序 (UI)
- 用于发送消息。您的应用程序应该将消息放入同步队列中。发送消息的线程从该队列中读取,并在队列中没有任何内容时阻塞。每条消息(对话?)有 1 个似乎有点过分了。
- 用于读取(接收)消息,并在有新消息可用时向 UI 发送事件。
关于你的ID的唯一性,这个ID是不是只是一条消息(奇怪)、一次对话、一个聊天室……
客户端应该向服务器发送一条没有 ID 的消息,说嘿我想向那个人/房间发送一条消息。如果您想要一个 ID,那么服务器可以在处理它时生成一个 ID,然后客户端将收到带有 ID 的消息。不确定他们会用它做什么。
消息应该有一个“收件人/目的地”字段(它已经有),该字段应该足以将消息组合到对话中。
关于java - 请求-响应消息格式和算法设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22047330/