2017-02-09 1 views
-2

Я искал всюду, в том числе здесь, для возможных решений и пробовал некоторые из ответов, которые я нашел без успеха.Невозможно прочитать ответ сокета C-сервер на Java-клиент

Я реализовал простой клиент Java tcp socket. Клиент отлично работает с одним сервером Java, но у меня возникают проблемы с получением ответа от сервера, закодированного в C. . Сервер, похоже, правильно обрабатывает транзакцию и отправляет ответ соответствующим образом. Проблема заключается в том, что клиент может получать входящий поток ответа. Это была моя первая реализация:

 String msg_out = message; 
     String reply; 

     //the stream object to transmit message to server 
     DataOutputStream outStream = new DataOutputStream(clientSocket.getOutputStream()); 

     outStream.writeBytes(msg_out + '\n'); 
     outStream.flush(); 

     //try to break away from locked read 
     //clientSocket.setSoTimeout(10000); 

     //initial implementation 
     //the object to receive reply server 
     BufferedReader replyStream = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); 
     reply = replyStream.readLine(); 

     System.out.println("Reply from "+ host + ":" + port + " -> " + reply); 

Я скачал Wireshark и использовал его для мониторинга трафика TCP пакетов между клиентом и сервером в соответствующем порту сокет сервера прослушивает. Я видел несколько предложений в других потоках с похожими темами, я, к сожалению, не смог заставить ни одно из этих решений работать для меня. Я обнаружил, что пакет, содержащий ответ, имеет значение флага, установленное в PSH (для того, чтобы не загружать пар при получении, немедленно обработать). Я думал, что клиент Java, пытаясь буферизовать ответ, вызвал перезагрузку соединения (RST, который появляется в пакете отказа, который является следующим, который возникает) из-за этого флага. Я попытался тестирование с помощью этой реализации я нашел в потоке здесь, пытаясь прочитать ответ побайтно, но не дали никаких результатов:

try { 
      DataInputStream in = new DataInputStream(clientSocket.getInputStream()); 
      int bytesRead = 0; 
      byte[] messageByte = new byte[1000]; 
      boolean end = false; 
      String messageString = ""; 
      messageByte[0] = in.readByte(); 
      messageByte[1] = in.readByte(); 
      ByteBuffer byteBuffer = ByteBuffer.wrap(messageByte, 0, 2); 

      int bytesToRead = byteBuffer.getShort(); 
      System.out.println("About to read " + bytesToRead + " octets"); 

      //The following code shows in detail how to read from a TCP socket 

      while(!end) 
      { 
       bytesRead = in.read(messageByte); 
       messageString += new String(messageByte, 0, bytesRead); 
       if (messageString.length() == bytesToRead) 
       { 
        end = true; 
       } 
      } 


      System.out.println("Server Reply: " + messageString); 
     } catch (Exception e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

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

Вот результаты пытаются запустить процесс комм клиента/сервера:

[2/10/17 14:23:49:658 EST] 00000031 SystemOut  O Outgoing transaction message:C00052!GDT43000KU!01!D-10!G-11!NORMAL!|     
[2/10/17 14:23:49:658 EST] 0000011e SystemOut  O Buffersize in stream:8192 
[2/10/17 14:23:49:737 EST] 0000011e SystemOut  O About to read 12336 octets 
[2/10/17 14:23:49:737 EST] 0000011e SystemErr  R java.net.SocketException: Connection reset 
[2/10/17 14:23:49:737 EST] 0000011e SystemErr  R  at java.lang.Throwable.<init>(Throwable.java:67) 
[2/10/17 14:23:49:737 EST] 0000011e SystemErr  R  at java.net.SocketInputStream.read(SocketInputStream.java:118) 
[2/10/17 14:23:49:737 EST] 0000011e SystemErr  R  at java.io.DataInputStream.read(DataInputStream.java:94) 
[2/10/17 14:23:49:737 EST] 0000011e SystemErr  R  at com.gf.btv.RTDLTSS.domain.LTSSClient.TCPClientRequest(LTSSClient.java:141) 
[2/10/17 14:23:49:737 EST] 0000011e SystemErr  R  at com.gf.btv.RTDLTSS.helper.LTSSClientThread.run(LTSSClientThread.java:147) 
[2/10/17 14:23:49:737 EST] 0000011e SystemErr  R  at java.lang.Thread.run(Thread.java:736) 
+0

Вы уверены, что отправлены в Big Endian? Некоторые программы на C предполагают, что они малочисленны, –

+1

* Что на самом деле происходит * при попытке запустить клиент? – immibis

+1

Какой протокол используется сервером для ответа? Документировано ли это на уровне байтов? Как вы можете узнать, делает ли ваш клиент правильные вещи, если вы не знаете, что ожидает от него сервер? (У вас есть протокольная документация? Или вам нужно перепроектировать протокол? Если у вас есть протокольная документация, поделитесь им. Если вам нужно перепроектировать протокол, покажите нам байты, которые сервер отправил вам, чтобы мы могли помочь вам сделайте это.) –

ответ

0

RST не имеет ничего общего с PSH или буферным читателем, но если вам нужно прочитать Двоичные читатель не подходит. RST указывает, что сверстник закрыл соединение, прежде чем вы его прочитали, что свидетельствует о том, что вы используете неправильный протокол. Неверно, что протокол запроса основан на линии, но протокол ответа имеет длину-префикс. Тот или другой, или что-то еще.

Если вы определили, что это на самом деле представляет собой протокол длины слова префикс, попробуйте следующее:

int messageLength = in.readShort(); 
byte messageBytes = new byte[messageLength]; 
in.readFully(messageBytes); 
// etc. 

Но вам нужно подтверждение фактического протокола. Угадайте, что вы не найдете вас там.

+0

Я попрошу еще раз убедиться, что мы знаем об энтиансе, но я действительно не думаю, что проблема в этом. – rocklandcitizen

+0

Вы должны снова спросить, знаете ли вы о протоколе *. Вы уже используете два здесь, и маловероятно, что оба они верны. Вполне возможно, что * ни * верно. – EJP

+0

Отмечу, что предполагаемое значение «короткое» (2 байта int) равно 12336, что является значением для двух байтов, каждый из которых содержит символ ASCII «0». Я подозреваю, что сервер фактически отправляет либо длину, либо какое-то другое значение в форме символа. –

Смежные вопросы