java - 请求-响应消息格式和算法设计

标签 java android multithreading networking chat

我正在编写一个 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 个线程:

  1. 一个用于主应用程序 (UI)
  2. 用于发送消息。您的应用程序应该将消息放入同步队列中。发送消息的线程从该队列中读取,并在队列中没有任何内容时阻塞。每条消息(对话?)有 1 个似乎有点过分了。
  3. 用于读取(接收)消息,并在有新消息可用时向 UI 发送事件。

关于你的ID的唯一性,这个ID是不是只是一条消息(奇怪)、一次对话、一个聊天室……

客户端应该向服务器发送一条没有 ID 的消息,说嘿我想向那个人/房间发送一条消息。如果您想要一个 ID,那么服务器可以在处理它时生成一个 ID,然后客户端将收到带有 ID 的消息。不确定他们会用它做什么。

消息应该有一个“收件人/目的地”字段(它已经有),该字段应该足以将消息组合到对话中。

关于java - 请求-响应消息格式和算法设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22047330/

相关文章:

android - 逻辑 : how to search a local network for a custom service

java - 示例案例的建议锁

.net - 为什么创建一个新线程比让它们保持空闲更昂贵?

java - 如何防止调整 SWT 组合的大小?

android - 设置Google Merchant帐户后如何将Android应用程序更改为付费?

android - 如何自定义Action Bar Style?

使用 Process() 和多线程的 Swift 命令行工具在一定数量的执行轮次(~3148)后崩溃

设置后Java数组引用为空

java - TextView 的 Android 自定义属性

java - 以正确的顺序绘制事物,Java