Надежный TCP / IP в Java - PullRequest
2 голосов
/ 04 августа 2011

Есть ли способ обеспечить надежную связь (отправителю сообщают, что отправленное сообщение уже получено получателем), используя библиотеку Java TCP / IP в java.net. *? Я понимаю, что одним из преимуществ TCP над UDP является его надежность. Тем не менее, я не мог получить такую ​​уверенность в эксперименте ниже:

Я создал два класса:

1) echo server => всегда отправляет обратно полученные данные.

2) client => периодически отправлять эхо-серверу сообщение «Hello world».

Они запускались на разных компьютерах (и работали отлично). Во время выполнения я отключил сеть (отключил кабель локальной сети). После отключения сервер все еще ожидает данные, пока не пройдет несколько секунд (в конечном итоге возникло исключение). Аналогичным образом, клиент также продолжает отправлять данные до тех пор, пока не пройдет несколько секунд (возникает исключение).

Проблема в том, что objectOutputStream.writeObject(message) не гарантирует статус доставки сообщения (я ожидаю, что оно заблокирует поток, продолжит повторную отправку данных до доставки). Или, по крайней мере, мне сообщают, какие сообщения отсутствуют.

Код сервера:

import java.net.*;
import java.io.*;

import java.io.Serializable;

public class SimpleServer {
    public static void main(String args[]) {
        try {
            ServerSocket serverSocket = new ServerSocket(2002);
            Socket socket = new Socket();
            socket = serverSocket.accept();
            InputStream inputStream = socket.getInputStream();
            ObjectInputStream objectInputStream = new ObjectInputStream(
                    inputStream);

            while (true) {
                try {
                    String message = (String) objectInputStream.readObject();
                    System.out.println(message);
                    Thread.sleep(1000);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

Код клиента:

import java.net.*;
import java.io.*;

public class SimpleClient {
    public static void main(String args[]) {
        try {
            String serverIpAddress = "localhost"; //change this

            Socket socket = new Socket(serverIpAddress, 2002);
            OutputStream outputStream = socket.getOutputStream();
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(
                    outputStream);

            while (true) {
                String message = "Hello world!";
                objectOutputStream.writeObject(message);

                System.out.println(message);
                Thread.sleep(1000);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Ответы [ 5 ]

3 голосов
/ 04 августа 2011

Если вы хотите этот уровень гарантий, это звучит так, как будто вы действительно хотите JMS.Это может гарантировать не только то, что сообщения были доставлены, но и были обработаны правильно.то есть нет смысла иметь очень надежную доставку, если она может быть отклонена из-за ошибки.

Вы можете отслеживать, какие сообщения ожидают, а какие потребители отстают.Наблюдайте за продюсером, чтобы увидеть, какие сообщения он отправляет, и сохраните сообщения, когда он выключен, и доступны, когда он перезапустится.т.е. надежная доставка, даже если потребитель перезапущен.

3 голосов
/ 04 августа 2011

Если вам необходимо знать, какие сообщения поступили в одноранговое приложение, одноранговое приложение должно отправить подтверждения.

1 голос
/ 04 августа 2011

Ваше базовое предположение (и понимание TCP) здесь неверно.Если вы отключите, а затем снова подключите, сообщение, скорее всего, не будет потеряно.
Это сводится к тому, как долго вы хотите, чтобы отправитель ждал.Один час, один день?Если бы вы сделали тайм-аут один день, вы бы отключили на два дня и все еще сказать «не работает».

Таким образом, гарантированная доставка заключается в том, что «либо данные доставлены, либо вас информируют».Во втором случае вам нужно решить это на уровне приложения.

1 голос
/ 04 августа 2011

Вы можете использовать опцию сокета SO_KEEPALIVE, которая приведет к закрытию соединения, если данные не передаются через сокет в течение 2 часов. Однако очевидно, что во многих случаях это не обеспечивает уровень контроля, который обычно требуется приложениям.

Вторая проблема заключается в том, что некоторые реализации стека TCP / IP работают плохо и могут оставить ваш сервер с висящими открытыми соединениями в случае сбоя сети.

Поэтому я бы посоветовал добавить пульс на уровне приложения между вашим клиентом и сервером, чтобы обе стороны остались живы. Это также дает преимущество в разрыве соединения, если, например, сторонний клиент остается живым, но перестает отвечать на запросы и, следовательно, перестает отправлять тактовые импульсы.

1 голос
/ 04 августа 2011

TCP всегда надежен.Вам не нужны подтверждения.Однако, чтобы проверить, что клиент работает, вы также можете использовать поток UDP с подтверждениями.Как пинг?ПОНГ!система.Также могут быть настройки TCP, которые вы можете настроить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...