2016-05-31 10 views
0

Ich verwende einen Server (C++ Winsock) und einen Client (Java) auf meinem PC.Winsock C++ - Java-Verbindung Langsame Geschwindigkeit

Ich sende eine große Byte-Array von meinem Client an den Server und während die Übertragung ohne Fehler abgeschlossen ist, bekomme ich eine sehr langsame Übertragungsgeschwindigkeit. Um ein Beispiel zu geben, dauert die Übertragung für eine Array-Größe von 200.000 Bytes 3-5 Sekunden (etwa 50 kB/s).

Ist das normal? Ich bin kein Experte, aber sollte ich nicht viel höhere Geschwindigkeiten (ca. 1 MB/s) durch das LAN erreichen?

Hier ist meine vereinfachte Code:

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

und 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

Sie sind der Champion, war es der gepufferte Ausgang :) New Geschwindigkeit 64 MB/s ... 1000-mal schneller! Vielen Dank, ich habe seit Tagen Fehler behoben. Kannst du es als Antwort posten, damit ich es annehmen kann? – Theo

+0

getan, glücklich, um zu helfen. – vaxquis

Antwort

0

Entweder wickeln Sie Ihre OutputStream in BufferedOutputStream oder Ihr nur Puffer Ausgabe manuell (z. B. indem zuerst die Bytes in ein Array gesammelt werden und dann #write(byte[]) verwendet wird. Das Senden eines Pakets mit jedem Byte muss extrem s sein niedrig - siehe Size of empty UDP and TCP packet?; Leeres TCP-Paket ist 64 Bytes, das sind 64 + 1 Bytes, die für 1 Byte Daten gesendet werden, was Ihnen ~ 1/65 der möglichen Übertragungsrate gibt (YMMV, Sie können sogar einen höheren Anstieg der Übertragungsraten sehen, wenn Sie zusätzlich Schweres loswerden Overhead von VM -> OS Kommunikation für jeden einzelnen writeByte Befehl).

Daumenregel für den direkten Nettotransfers ist, dass, wenn Sie beabsichtigen, viel weniger senden als ein gewöhnlicher Ethernet-Paket (dh deutlich weniger als 1KiB, zB 100 Bytes) wiederholt über einen kurzen Zeitraum, dann ist es eine gute Idee, um es zuerst zu puffern und kollektiv zu senden.