2010-10-28 2 views
4

Java Socket ServerSocket.Receive .NET() ne recevant pas de grandes flux de données de Java SocketServer


J'ai un processus Java qui crée un écouteur sur un Socket TCP en utilisant java.io. ServerSocket quelque chose comme ça (simplifié):

ServerSocket server = new ServerSocket(4444,20); 
server.accept(); 

le processus Java Déclenché un thread de travail lorsqu'une demande est reçue et le travailleur envoie alors une chaîne JSON en utilisant java.io.PrintWriter et java.net.Socket:J'ai simplifié le code Java mais c'est essentiellement tout ce qu'il fait.


.NET Socket client


Ensuite, j'ai une application .NET qui communique avec la machine hébergeant ce processus Java:

//Create Connection 
Socket clientSocket = new Socket(AddressFamily.InterNetwork, 
           StreamType.Stream, ProtocolType.Tcp); 
mySocket.Connect("192.168.1.102", 4444); 

//Initialize Byte Buffer Larger than Expected JSON String and Read Bytes 
byte[] receivedData = new byte[524288]; 
int numberOfBytes = clientSocket.Receive(receivedData, SocketFlags.None); 
clientSocket.Close(); 

//Populate a new byte array of the exact size received with the received data 
byte[] formatedBytes = new byte[numberOfBytes]; 
for (int i=0; i< numberOfBytes; i++) 
{ 
    formatedBytes[i] = receivedData[i]; 
} 

//Convert Byte Array to String & Output Results 
Response.ClearContent(); 
Response.ContentType("text/plain"); 
Response.Write(new System.Text.ASCIIEncoding().GetString(receivedData)); 

Mon problème est que pour Quelle que soit la raison, cette implémentation ne fonctionne pas lorsque j'essaie d'envoyer des chaînes JSON légèrement plus grandes sur le flux Socket. Avec de petites tailles de données (moins de 2 Ko) j'ai testé avec succès cette implémentation avec plus de 100 clients se connectant et recevant des données sans aucun problème. Cependant, essayer d'augmenter la taille de la chaîne JSON à environ 256Ko. L'augmentation de la taille du tableau de tampons n'aide pas non plus - il semble que l'application .NET abandonne la connexion avant que toutes les données ne soient transmises, ou que l'application Java n'envoie pas la totalité de la chaîne en utilisant PrintWriter.

Tout aperçu de cette question serait grandement apprécié - je publierai des mises à jour si je fais des progrès moi-même.


Voici la solution que j'ai trouvée - Le serveur fonctionne très bien maintenant! Merci encore!


byte[] receivedData = new byte[512000]; // 4 Meg Buffer 

    Socket mySocket = new Socket(AddressFamily.InterNetwork, 
           SocketType.Stream, ProtocolType.Tcp); 
    mySocket.Connect("172.26.190.205", 4444); 
    mySocket.ReceiveBufferSize = 8192; 

    int numberOfBytesRead = 0; 
    int totalNumberOfBytes = 0; 
    do 
    { 
     numberOfBytesRead = mySocket.Receive(receivedData,totalNumberOfBytes , 
          mySocket.ReceiveBufferSize,SocketFlags.None); 
     totalNumberOfBytes += numberOfBytesRead; 
    } 
    while (numberOfBytesRead > 0); 
    mySocket.Close(); 

    byte[] formatedBytes = new byte[totalNumberOfBytes ]; 
    for (int i = 0; i < totalNumberOfBytes ; i++) 
    { 
     formatedBytes[i] = receivedData[i]; 
    } 
    Response.ClearContent(); 
    Response.ContentType = "text/plain"; 
    Response.Write(new System.Text.ASCIIEncoding().GetString(formatedBytes)); 

Répondre

3

Alors que TCP est un flux dans le concept, la propriété intellectuelle sous-jacente envoie et reçoit des paquets . Pour l'application cela signifie que vous toujours lire à partir de la socket dans une boucle, car une seule "écriture" par l'expéditeur peut entraîner plusieurs "lectures" par le récepteur, et l'inverse.

Cela se résume au fait que c'est à l'implémentation de la pile TCP/IP de diviser les données que vous envoyez en paquets. Le côté récepteur, encore une fois la pile réseau, ne sait pas combien d'octets il faut attendre. Il prend juste ce qu'il a et réveille le processus qui attend sur ce socket, s'il y en a un, ou tamponne les octets sinon.

Votre cas est simple: continuez à lire depuis le socket jusqu'à ce que vous voyiez EOF, c'est-à-dire zéro octet lu.Mais en général, vous avez besoin d'un protocole au niveau de l'application qui définit les longueurs des messages, établit des règles pour les limites des messages ou incorpore des informations de longueur explicite dans les messages eux-mêmes.

+0

J'apprécie les informations supplémentaires - ce projet a été mon premier effort dans la programmation réseau et a été très intéressant. Je reçois maintenant l'intégralité de l'ensemble de données de .NET et travaille actuellement à essayer de maintenir le bon ordre des données à mesure qu'elles arrivent. Il semble que je reçois les paquets dans le désordre. – John

+0

Hmm, c'est * pas possible * avec TCP car il maintient le séquençage de tous les octets envoyés/reçus sur la * même * connexion. Je blâmerais le filetage ici - est-ce que vous supposez que si le fil a été lancé en premier, il sera envoyé en premier? C'est une supposition cassée. –

+0

Je pensais que c'était le cas avec TCP - en examinant de plus près ce n'est certainement pas ce qui se passe non plus. Threading peut en faire partie - je vais regarder de plus près tout maintenant que je vois comment la fonction de réception se comporte et je posterai une mise à jour bientôt. J'espère avoir compris cela dans un petit peu. – John

0

// Initialiser octet tampon plus grand que Expected JSON cordes et de lecture Octets octet [] receivedData = new octet [524288]; int nombreDeBytes = clientSocket.Receive (receivedData, SocketFlags.None); clientSocket.Close();

Ok, cela lit tous les octets qui arrivent dans le tampon. Puis ferme le flux. UPS.

Lire la documentation - pour la méthode de réception. Vous devez l'appeler à plusieurs reprises jusqu'à ce que vous n'obteniez plus de données. Il bloquera jusqu'à ce que QUELQUES données arrivent, puis retourner ceci. Il n'attendra PAS que TOUTES les données soient arrivées.

Questions connexes