2016-05-31 87 views
0

我在PC上運行服務器(C++ Winsock)和客戶端(Java)。Winsock C++ - Java Connection Slow Speed

我發送一個大的字節數組從我的客戶端到服務器,而傳輸完成沒有任何錯誤,我得到一個非常慢的傳輸速度。舉一個例子,對於200.000字節的數組大小,傳輸需要3-5秒(大約50kB/s)。

這是正常的嗎?我不是專家,但是我不應該通過局域網達到更高的速度(大約1Mb/s)嗎?

這裏是我的簡化代碼:

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

和服務器(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

你是冠軍,它是緩衝輸出:)新速度是64Mb/s ... 1000倍更快!非常感謝,我一直在排查幾天。你可以把它作爲答案發布,以便我可以接受它嗎? – Theo

+0

做完了,很高興能有所幫助。 – vaxquis

回答

0

要麼換你OutputStreamBufferedOutputStream,或者只是緩衝自己手動輸出(例如,首先將字節收集到一個數組中,然後使用#write(byte[])。發送每個字節的數據包必然非常s低 - 見Size of empty UDP and TCP packet?;空的TCP數據包是64個字節,即爲1個字節的數據發送64 + 1個字節,給你1/65的可能傳輸速率(YMMV,由於消除了額外的重量,你可能會看到傳輸速率更高的增加VM的開銷 - >每個單個的writeByte命令的OS通信)。

憑經驗直接「淨轉移的是,如果你打算髮送比通常的以太網數據包(即明顯比1KiB更少,例如100個字節)反覆在很短的時間要少得多,這是一個好主意首先緩衝並集體發送。