2016-05-31 88 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个字节)反复在很短的时间要少得多,这是一个好主意首先缓冲并集体发送。