Сообщение только читается клиентом после того, как сервер закрывает конец соединения в Java

Я пытался отправить сообщения ISO8583, созданные с помощью библиотеки JPOS на Java. Я написал простой код сокетного соединения для отправки сообщения. Я могу отправить сообщение успешно, но проблема в том, что сервер отправляет ответ вовремя, но сообщение не читается моим клиентским сокетом. Он считывает данные только после принудительного закрытия соединения (отсоединение сокета вручную) на сервере.

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

Вот мой пример кода для отправки:

logISOMsg(isoMsg);
byte[]  send_PackedRequestData = isoMsg.pack();
BufferedOutputStream outStream=null;
BufferedReader receiveStream=null;

Socket connection = new Socket("127.0.0.1", 5874);
if (connection.isConnected()) {

    outStream = new BufferedOutputStream(connection.getOutputStream());
    outStream.write(send_PackedRequestData);
    outStream.flush();
}

и для чтения:

if (connection.isConnected()) {
    receiveStream = new BufferedReader(new InputStreamReader(connection.getInputStream()));
    String isoMessage = receiveStream.readLine();

    ISOMsg isoMsg1 = new ISOMsg(); 
    isoMsg1.setPackager(packager);   

    byte[] bIsoMessage = new byte[isoMessage.length()];   
    for (int i = 0; i < bIsoMessage.length; i++) {
        bIsoMessage[i] = (byte) (int) isoMessage.charAt(i); 
    }                                
    isoMsg1.unpack(bIsoMessage); 

    System.out.println("MTI='"+isoMsg1.getMTI()+"'");     
    for (int i=1; i<=isoMsg1.getMaxField(); i++) {
        if (isoMsg1.hasField(i))
            System.out.println("DE : "+ i + " =  " + isoMsg1.getString(i) + "");
    }
}

1 ответ

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

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

На стороне получателя, однако, вы используете BufferedReader.readLine(), который использует третий вариант и ждет новой строки. Видимо, ваше сообщение не заканчивается новой строкой, и поэтому читатель бесконечно зависает в ожидании новой строки.

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

Кроме того, вы смешиваете строки и байтовые массивы, что является ошибкой. Отправитель отправляет необработанный байтовый массив. На стороне получателя происходит то, что InputStreamReader внутренне преобразует байтовый массив в строку. Эта операция декодирует байты в символы, используя набор символов, такой как UTF-8. Вы даже не указываете, какой набор символов использовать, поэтому вывод может быть в значительной степени произвольным. После этого ваш код преобразует строку обратно в байтовый массив, но этот код неверен и не гарантирует восстановления исходного содержимого (результирующий байтовый массив может отличаться от того, который отправил сервер).

Таким образом, вы не должны использовать какой-либо класс Reader на стороне получателя, если вы не используете класс Writer на стороне отправителя. Вместо этого используйте только потоки, как вы делаете при отправке.

Другие вопросы по тегам