2017-02-09 5 views
-2

J'ai recherché partout des solutions possibles et essayé certaines des réponses que j'ai trouvées sans succès. J'ai implémenté un simple client Java tcp socket. Le client fonctionne très bien avec un serveur Java mais j'ai toujours des problèmes pour recevoir la réponse d'un serveur codé en C. Le serveur semble gérer correctement la transaction et il envoie une réponse en conséquence. Le problème réside dans le fait que le client puisse recevoir le flux entrant de la réponse. Ce fut ma première mise en œuvre:Impossible de lire la réponse de la socket Serveur C vers le client Java

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

J'ai téléchargé Wireshark et utilisé pour surveiller le trafic de paquets tcp entre le client et le serveur dans le port correspondant du socket serveur est à l'écoute. J'ai vu plusieurs suggestions dans d'autres sujets avec des sujets similaires, je n'ai malheureusement pas pu obtenir l'une de ces solutions pour travailler pour moi. J'ai trouvé que le paquet contenant la réponse a la valeur de l'indicateur mis à PSH (pour ne pas tamponner la vapeur lors de la réception, traiter immédiatement). Je pensais que le client Java en tentant de mettre en tampon la réponse provoquait la réinitialisation de la connexion (RST qui apparaît dans le paquet d'échec, qui est le suivant) à cause de cet indicateur. J'ai essayé de tester cette mise en œuvre, j'ai trouvé dans un thread ici pour essayer de lire l'octet de réponse par octet, mais en vain:

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

Je n'ai pas accès au code source du serveur C, mais son développeur ne jure que pour moi que le problème n'est pas de son côté et je le crois. Je sais aussi qu'il ne peut pas y apporter de modifications car cela fonctionne avec toutes les autres architectures clientes utilisées, celle que je code est le seul client Java qui interagit avec ce serveur basé sur C. Y a-t-il une erreur dans ma mise en œuvre ou existe-t-il une autre implémentation que je pourrais utiliser pour lire le flux de réponses de manière plus infaillible?

est ici les résultats d'essayer de lancer le processus de comm client/serveur:

[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

Êtes-vous sûr d'envoyer à Big Endian? Certains programmes C supposent un peu d'endian, –

+1

* Que se passe-t-il réellement * lorsque vous essayez d'exécuter le client? – immibis

+1

Quel protocole utilise le serveur pour la réponse? Est-il documenté au niveau des octets? Comment pouvez-vous savoir si votre client fait la bonne chose si vous ne savez pas ce que le serveur attend de lui? (Si vous avez une documentation de protocole, partagez-la Si vous avez besoin d'une rétro-ingénierie du protocole, montrez-nous les octets que le serveur vous a envoyés afin que nous puissions essayer de vous aider –

Répondre

0

La TVD n'a rien à voir avec le PSH ou le lecteur en mémoire tampon, mais si vous avez besoin de lire binaire, le le lecteur n'est pas approprié. Le RST indique que l'homologue a fermé la connexion avant de la lire, ce qui indique clairement que vous utilisez le mauvais protocole. Il n'est pas crédible que le protocole de requête soit basé sur une ligne mais que le protocole de réponse soit basé sur un préfixe de longueur de mot. L'un ou l'autre, ou autre chose.

Si vous déterminez qu'il est vraiment un protocole longueur mot-préfixe, essayez ceci:

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

Mais vous avez besoin de confirmation du protocole réel. Les devinettes ne vous y amèneront pas.

+0

Je vais demander à nouveau de m'assurer que nous sommes au courant de l'endianess, mais je ne pense vraiment pas que le problème est avec ceci. – rocklandcitizen

+0

Vous devriez demander à nouveau de vous assurer que vous êtes au courant du protocole *. * Vous en utilisez déjà deux ici, et il est hautement improbable que les deux soient corrects. Tout à fait possible que * ni * est correct. – EJP

+0

Je note que la valeur supposée 'courte' (2 octets int) est 12336, qui est la valeur pour deux octets contenant chacun le caractère ASCII '0'. Je suspecte que le serveur envoie réellement la longueur ou une autre valeur dans la forme de caractère. –