2009-12-05 3 views
0

J'ai un client Java qui envoie des chaînes UTF-8 à un serveur TCP C#, j'utilise un DataOutputStream pour envoyer les chaînes. Le code ressemble à ceci:DataOutputStream non videur

public void sendUTF8String(String ar) { 
    if (socket.isConnected()) { 
     try { 
      dataOutputStream.write(ar.getBytes(Charset.forName("UTF-8"))); 
      dataOutputStream.flush(); 
     } catch (IOException e) { 
      handleException(e); 
     } 
    } 
} 

Le problème est que le vidage ne semble pas fonctionner correctement. Si j'envoie deux chaînes proches l'une de l'autre, le serveur reçoit un seul message avec les deux chaînes. Le tout fonctionne si je fais un Thread.sleep (1000) entre les appels, ce n'est évidemment pas une solution. Qu'est-ce qui me manque?

Répondre

7

flush() ne garantit pas l'envoi d'un paquet de données. Votre pile TCP/IP est libre de regrouper vos données pour une efficacité maximale. Pire, il y a probablement un tas d'autres piles TCP/IP entre vous et votre destination, et ils sont libres de faire la même chose.

Je pense que vous ne devriez pas compter sur le groupage de paquets. Insérez un terminateur/diviseur logique dans vos données et vous serez du bon côté.

+3

Je commençais une réponse aussi, mais il ne a ajouté que la mise en mémoire tampon sur le côté de la réception pourrait gâcher tout vous chasse d'eau pourrait faire sur le client, même si vous pouviez tirer de manière fiable (ce qui en général vous pouvez). Mais peu importe ce que vous faites sur le client, le serveur tamponnera toujours ses données de socket. – PSpeed

2

Vous ne devriez pas vous inquiéter de la façon dont les données sont décomposées en paquets.

Vous devez inclure la longueur de la chaîne dans vos messages, puis à la fin de la réception, vous devez d'abord lire la longueur. Ainsi, par exemple d'envoyer vous faire

byte[] arbytes = ar.getBytes(Charset.forName("UTF-8")); 
output.writeInt(arbytes.length) 
output.write(arbytes) 

puis dans votre lecteur vous

byte[] arbytes = new byte[input.readInt()]; 
for(int i = 0; i < len; i++){ 
    arbytes[i] = input.read(); 
} 
//convert bytes back to string. 

Vous ne pouvez pas simplement appeler input.read (arbytes) parce que la fonction de lecture ne lit pas nécessairement toute la longueur du tableau. Vous pouvez faire une boucle où vous lisez un morceau à la fois mais le code pour cela est un peu plus complexe.

De toute façon, vous avez l'idée.


Aussi, si vous vraiment voulez contrôler ce qui se passe dans quels paquets, vous pouvez utiliser Datagram Sockets, mais si vous le faites alors la livraison du paquet n'est pas garanti.

1

Le socket envoie un flux de données, pas de messages. Vous ne devez pas compter sur les paquets que vous recevez ayant la même taille que ceux envoyés. Les paquets peuvent être regroupés comme vous avez pu le voir, mais ils peuvent aussi être brisés. Utilisez la suggestion de @Chad Okere sur la façon de vous assurer que les blocs sont les mêmes qu'ils ont été envoyés.

Cependant, dans votre cas, vous pouvez simplement utiliser

dataOutputStream.writeUTF(ar); // sends a string as UTF-8 

et

String text = dataInputStream.readUTF(); // reads a string as UTF-8 
Questions connexes