2016-05-31 3 views
0

Je cours un serveur (C++ Winsock) et un client (Java) sur mon PC. J'envoie un grand tableau d'octets de mon client vers le serveur et pendant que le transfert est terminé sans erreur, j'obtiens une vitesse de transfert très lente. Pour vous donner un exemple, pour une taille de tableau de 200 000 octets, le transfert prend 3 à 5 secondes (environ 50 Ko/s).Winsock C++ - Vitesse de connexion Java

Est-ce normal? Je ne suis pas un expert mais ne devrais-je pas atteindre des vitesses beaucoup plus grandes (environ 1Mb/s) à travers le LAN?

Voici mon code simplifié:

client (Java)

import ... 

    public class Client { 
     public static void main(String[] args) throws IOException { 

      OutputStream outToServer; 
      DataOutputStream out = null; 
      String serverHostname = new String ("..."); 
      int port = ...; 

      Socket client = null; 
      try { 
       client = new Socket(serverHostname, port); 
       outToServer = client.getOutputStream(); 
       out = new DataOutputStream(outToServer); 

       int size = 200000; 
       byte[] b = new byte[size]; 
       new Random().nextBytes(b); 
       for(int i = 0 ; i < size ; i++){ 
        out.writeByte(b[i]); 
       }   
       out.close(); 
      } catch (UnknownHostException e) ...//Exit 
       catch (IOException e) ...//Exit 

      client.close(); 
     } 
    } 

et Server (C++, Winsock)

#undef UNICODE 
    #define WIN32_LEAN_AND_MEAN 
    #include <windows.h> 
    #include <winsock2.h> 
    #include <ws2tcpip.h>... 
    // Need to link with Ws2_32.lib 
    #pragma comment (lib, "Ws2_32.lib") 
    // #pragma comment (lib, "Mswsock.lib") 
    #define DEFAULT_BUFLEN 512 
    #define DEFAULT_PORT "..." 

    int __cdecl main(void) 
    { 
     WSADATA wsaData; 
     int iResult; 
     SOCKET ListenSocket = INVALID_SOCKET; 
     SOCKET ClientSocket = INVALID_SOCKET; 
     struct addrinfo *result = NULL; 
     struct addrinfo hints; 
     int iSendResult; 
     char recvbuf[DEFAULT_BUFLEN]; 
     int recvbuflen = DEFAULT_BUFLEN; 

     // Initialize Winsock 
     iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); 
     if (iResult != 0) //Return 

     ZeroMemory(&hints, sizeof(hints)); 
     hints.ai_family = AF_INET; 
     hints.ai_socktype = SOCK_STREAM; 
     hints.ai_protocol = IPPROTO_TCP; 
     hints.ai_flags = AI_PASSIVE; 

     // Resolve the server address and port 
     iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result); 
     if (iResult != 0) ...//Return 

     // Create a SOCKET for connecting to server 
     ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); 
     if (ListenSocket == INVALID_SOCKET) ...//Return 

     // Setup the TCP listening socket 
     iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen); 
     if (iResult == SOCKET_ERROR) ...//Return 

     freeaddrinfo(result); 

     iResult = listen(ListenSocket, SOMAXCONN); 
     if (iResult == SOCKET_ERROR) ...//Return 

     // Accept a client socket 
     ClientSocket = accept(ListenSocket, NULL, NULL); 
     if (ClientSocket == INVALID_SOCKET) ...//Return 

     // No longer need server socket 
     closesocket(ListenSocket); 
     // Receive until the peer shuts down the connection 
     int bytes = 0; 
     do { 
      iResult = recv(ClientSocket, recvbuf, recvbuflen, 0); 
      if (iResult > 0) 
       bytes += iResult; 
      else if (iResult == 0) 
       //Connection Closing 
      else 
       ...//Return 

     } while (iResult > 0); 

     printf("Received %d bytes\n", bytes); 

     ...//Shutdown and Return 
    } 
+1

vous êtes le champion, c'était la sortie bufférisée :) La nouvelle vitesse est 64Mb/s ... 1000 fois plus rapide! Merci beaucoup, j'ai dépannage pendant des jours. Pouvez-vous l'afficher comme réponse pour que je puisse l'accepter? – Theo

+0

fait, heureux d'être utile. – vaxquis

Répondre

0

enveloppez votre OutputStream dans BufferedOutputStream, ou tout simplement tampon votre sortie manuelle (par exemple, en collectant d'abord les octets dans un tableau, puis en utilisant #write(byte[])) L'envoi d'un paquet avec chaque octet est forcément extrêmement faible - voir Size of empty UDP and TCP packet?; Le paquet TCP vide est de 64 octets, soit 64 + 1 octets envoyés pour un octet de données, vous donnant ~ 1/65 du taux de transfert possible (YMMV, vous pouvez voir une augmentation encore plus élevée des taux de transfert en raison de se débarrasser de lourds surcharge de la communication VM -> OS pour chaque commande writeByte).

Règle générale pour les transferts nets directs » est que si vous avez l'intention d'envoyer beaucoup moins qu'un paquet Ethernet habituelle (soit sensiblement inférieure à 1KiB, par exemple 100 octets) à plusieurs reprises sur une courte période, il est une bonne idée pour le tamponner d'abord et l'envoyer collectivement.