Winsock C++ - Java 连接速度慢

Winsock C++ - Java Connection Slow Speed

我在我的 PC 上 运行 一个服务器 (C++ Winsock) 和一个客户端 (Java)。

我正在从我的客户端向服务器发送一个大字节数组,虽然传输完成且没有任何错误,但我的传输速度非常慢。举个例子,对于 200.000 字节的数组大小,传输需要 3-5 秒(大约 50kB/s)。

这正常吗?我不是专家,但我不应该通过 LAN 达到更高的速度(大约 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
    }

要么将你的 OutputStream 包裹在 BufferedOutputStream, or just buffer your output manually (e.g. by first collecting the bytes into an array, and then using #write(byte[]). Sending a packet with each byte is bound to be extremely slow - see Size of empty UDP and TCP packet? 中;要么空 TCP 数据包是 64 字节,即 64+1 字节发送 1 字节数据,给你大约 1/65 的可能传输速率(YMMV,你可能会看到传输速率更高的增长,因为摆脱了额外的重VM 开销 -> 每个 writeByte 命令的 OS 通信)。

直接“网络传输”的经验法则是,如果您打算发送比通常的以太网数据包少得多的数据包(即明显小于 1KiB,例如 100 字节)重复时间较短,先缓冲再集中发送比较好。