Лучший способ связи между TCP-клиентом и сервером - PullRequest
2 голосов
/ 31 марта 2020

У меня есть система команд для связи между моим TCP-сервером и клиентом (Java). Я могу отправить определенные c команды моему Клиенту, если Клиент получил команду, он что-то выполнит.

В принципе, это работает. Но иногда мне нужно отправить команду + дополнительная информация. Проблема в том, что информация иногда отправляется слишком быстро. Поэтому некоторая информация будет потеряна / перепутана, и мой клиент не сможет выполнить запрос должным образом. Решением для меня было использовать Thread.sleep(), но это не чисто и не эффективно. Поскольку существует риск того, что информация не будет получена должным образом.

Мой сервер:

public void sendCommand(Socket socket) throws InterruptedException, IOException {
    writeMsg("CMD_POPUP", socket);
    Thread.sleep(150);
    writeMsg("foo", socket);
    Thread.sleep(150);
    writeMsg("bar", socket);
    Thread.sleep(150);
    writeMsg("baz", socket);
}

public void writeMsg(String message, Socket socket) throws IOException {
    DataOutputStream out = new DataOutputStream(socket.getOutputStream());
    out.writeUTF(message);
}

Мой клиент:

public void interpreteCommand(Socket socket) throws IOException {
    while (true) {
        switch (readMsg(socket)) {
            case "CMD_POPUP":
                System.out.println(readMsg(socket)); 
                System.out.println(readMsg(socket)); //Sometimes it would be 'bar' but also sometimes it would be 'baz'
                System.out.println(readMsg(socket)); //Sometimes it would be 'baz' but also sometimes it would be nothing
                break;
        }
    }
}

public String readMsg(Socket socket) throws IOException {
    DataInputStream in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
    return in.readUTF();
}

Ответы [ 2 ]

4 голосов
/ 31 марта 2020

Прежде всего, я не программист java. Однако tcp-соединения работают так же в других языках программирования.

TCP-соединения основаны на потоке, то есть нет начала или конца сообщения. TCP гарантирует только то, что данные поступают в правильном порядке.

Если вы отправляете «CMD_POPUP» и «foo» сразу после друг друга, вы не знаете, получите ли вы «CMD_POPUP», "CMD_POPUPfoo", "CMD_PO" et c. на другой стороне. Поскольку между каждым отправлением вы ожидаете определенное время c, данные обычно приходят один за другим. Но это не гарантировано, и я также считаю, что это не очень чистый способ сделать это.

Самый простой способ обойти это - отправить начальный символ в начале, символы-разделители между параметрами и конечный символ после каждого сообщения. например, "# CMD_POPUP% foo% bar $" или что-то в этом роде. Таким образом, вы можете записывать все, что получаете, в буфер, пока не получите конец сообщения, а затем обработать его.

3 голосов
/ 31 марта 2020

На самом деле вам не нужно Thread.sleep, вместо этого вы можете передать дополнительную информацию, дополненную самой командой, например writeMsg("foo;extrainformation", socket);, а с другой стороны разделить эту строку, где первая часть - команда. В противном случае вместо передачи string вы можете передать всю структуру object или json для лучшей реализации.

...