Проблема эффективности в следующем методе передачи данных через сокет-связь - PullRequest
0 голосов
/ 06 февраля 2019

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

1) У меня есть ПЛК, который действует как программа сокета сервера.И у меня есть программа Java Client Socket для чтения данных с сервера.

Так как здесь PLC является сервером, он устанавливает пассивную связь, а когда клиент инициирует связь, сервер предоставляет клиенту данные от определенногообласть, которая выглядит ниже Kishore Kumar Korada

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

Примечание: Каждый раз, когда клиентская программа должна получать аналогичные данные с одинаковымисмещения и длина.

2) Я не уверен, смогу ли я достичь этого с помощью одного сокетного соединения (пробовал, но не получил ожидаемого результата), считывал данные с сервера, обрабатывал их, сохранял их в db, а затем Закрытие сокета .И воссоздание сокета снова.И я делаю это через каждые 1 секунду. Это означает, что я создаю много сокетов.
Общая структура может быть описана в графическом виде, как показано ниже Kishore Kumar Korada
3) Код клиента, который я использовал для полученияданные с сервера ниже

try {
    socket = new Socket(host, port);
    is = socket.getInputStream();
    outputBuffer = new ByteArrayOutputStream();

    byte[] buffer = new byte[1024];
    int read;
    if((read = is.read(buffer)) != -1) {
        outputBuffer.write(buffer, 0, read);
    }
    /* All Processing work */
} catch (UnknownHostException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} catch (Exception e) {
    e.printStackTrace();
} finally {
    try {
        System.out.println("Before closing the socket");
        try {
            is.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("After closing the socket");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Я закрываю сокеты, как вы можете видеть здесь.И я запускаю один и тот же фрагмент кода каждую секунду в планировщике.

Имея всю эту структуру, я хотел бы задать следующие вопросы
1) Могу ли я получить те же данные, что и вы?см. первое изображение с одним соединением сокета каждый раз, когда мне разрешают читать ???Если да, можно было бы объяснить вкратце?
2) Выглядит ли мой фрагмент кода как программа клиентских сокетов?Я знаю, что закрыл там розетку.На самом деле, как я уже говорил, я выполняю один и тот же код каждую секунду.Если это не очень хорошая практика, не могли бы вы мне предложить один из них?
3) В целом, глядя на второе изображение, как получить одни и те же данные из области отправки снова и снова с одинаковым смещением?

1 Ответ

0 голосов
/ 13 февраля 2019

1) Могу ли я получать те же данные, которые вы видите на первом изображении, с одним соединением сокета каждый раз, когда мне разрешают читать ???Если да, можно объяснить вкратце?

Вы можете , но я бы не рекомендовал это.Поскольку вы получаете фиксированный объем данных каждую секунду и обрабатываете его сразу же после этого, я бы предпочел, чтобы одному потоку было поручено чтение данных из сокета, а другому потоку (или пулу потоков) - обработка входящих данных.Если обработка данных занимает больше одной секунды, и вы обрабатываете ее в том же потоке, что и Socket, резервное копирование данных будет выполняться очень быстро.

2) Мой фрагмент кода выглядит как клиентПрограмма сокетов?Я знаю, что закрыл там розетку.На самом деле, как я уже говорил, я выполняю один и тот же код каждую секунду.Если это не очень хорошая практика, не могли бы вы предложить мне одну из них?

Программы клиент / сервер могут отличаться по многим параметрам, поэтому нет правильного стандарта.Что касается альтернативных решений, см. То, что я написал выше.

3) В целом, глядя на второе изображение, как получить одни и те же данные из области отправки снова и снова с одинаковым смещением?

К счастью для вас, я создал и поддерживаю клиент / сервер framework под названием SimpleNet , который, я думаю, сделает это намного проще!

Пример кода для вашей программы, использующей SimpleNet, будет выглядеть следующим образом:

Client client = new Client();

client.onConnect(() -> {
    // Continuously read 52 bytes of data and invoke the callback when they arrive.
    client.readAlways(52, buffer -> {
        int realValue = buffer.getInt();  // 4 bytes
        int intValue = buffer.getShort(); // 2 bytes

        byte[] operatorNameBytes = new byte[18];
        buffer.get(operatorNameBytes);
        String operatorName = new String(operatorNameBytes);

        byte[] shiftIdBytes = new byte[10];
        buffer.get(shiftIdBytes);
        String shiftId = new String(shiftIdBytes);

        byte[] productIdBytes = new byte[16];
        buffer.get(productIdBytes);
        String productId = new String(productIdBytes);

        int status = buffer.getShort(); // 2 bytes

        // All processing work can occur here or be delegated to a thread pool.
    });
});

client.connect(host, port);

Если оставить соединение с сервером открытым, я думаю, что в итоге это будет стоить дешевле, чем необходимость постоянно создавать и уничтожать Socketобъекты.Кроме того, асинхронные обратные вызовы, которые использует SimpleNet, должны обеспечить его масштабируемость, если вы когда-нибудь решите отправить больше данных.

Примечание : при условии, что ваш сервер отправляет данные клиенту один раз в секунду, тогда пример будет работать для вас без необходимости что-либо менять.В противном случае вы можете изменить client.readAlways на client.read и использовать ScheduledExecutorService для вызова client.read один раз в секунду.Если ваш сервер отправляет данные клиенту только при первом подключении, вы также можете использовать client.read и просто повторно подключать клиент раз в секунду.

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