2017-02-09 5 views
-2

가능한 해결책을 찾기 위해 여기를 포함하여 어디에서나 검색해 보았지만 성공하지 못했던 답변을 시도했습니다.Java 클라이언트에 소켓 응답 C 서버를 읽을 수 없습니다.

간단한 Java TCP 소켓 클라이언트를 구현했습니다. 클라이언트는 하나의 Java 서버에서 제대로 작동하지만 C로 코딩 된 서버로부터 응답을 수신하는 데 계속 문제가 있습니다. 서버가 트랜잭션을 올바르게 처리하고있는 것으로 보입니다. 따라서 응답을 적절하게 보냅니다. 문제는 클라이언트가 응답의 들어오는 스트림을 수신 할 수 있다는 것입니다. 이 내 초기 구현했다 : 나는 Wireshark를 다운로드하고 서버 소켓이 수신 대기중인 해당 포트에서 클라이언트와 서버 사이의 TCP 패킷 트래픽을 모니터링하는 데 사용

 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); 

. 비슷한 주제의 다른 스레드에서 여러 제안을 보았습니다. 불행히도 이러한 솔루션 중 하나를 얻을 수 없었습니다. 나는 회신을 포함하는 패킷이 플래그 값을 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 서버의 소스 코드에 액세스 할 수없는 있지만 개발자가 맹세 : 여기 바이트로하지만 아무 소용이 응답 바이트를 읽으려고 내가 스레드에서 발견이 구현 테스트를 시도 그 문제는 그의 목적이 아니며 나는 그를 믿는다. 또한 사용중인 다른 모든 클라이언트 아키텍처에서 작동하므로 변경을 할 수 없다는 것을 알고 있습니다. 코딩하는 것은이 C 기반 서버와 상호 작용하는 유일한 Java 클라이언트입니다. 구현에 오류가 있습니까? 아니면 응답 스트림을 더 바보 같은 방식으로 읽는 데 사용할 수있는 다른 구현이 있습니까?

다음은 클라이언트/서버 통신 프로세스를 실행하려고 노력의 결과입니다 :

[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

나는 우리가 endianess를 알고 있는지 다시 한번 질문 할 것이지만, 나는 그 문제가 이것과 함께 있다고 생각하지 않는다. – rocklandcitizen

+0

* 프로토콜을 알고 있는지 다시 확인해야합니다. * 이미 여기에서 2 개를 사용하고 있으며 둘 다 올바르지 않을 가능성이 매우 높습니다. * 어느 것도 정확하지 않을 수도 있습니다. – EJP

+0

'short'(2 바이트 int) 값은 12336으로, ASCII 문자 '0'을 포함하는 2 바이트의 값입니다. 나는 서버가 실제로 길이 또는 다른 값을 문자 형식으로 보내고 있다고 생각한다. –