0

I'm running a server (C++ Winsock) and a Client (Java) on my PC.

I am sending a large byte array from my client to the server and while the transfer is completed without any errors, I'm getting a very slow transfer speed. To give you an example, for an array size of 200.000 bytes the transfer takes 3-5 seconds (around 50kB/s).

Is this normal? I'm no expert but shouldn't I be reaching much greater speeds (around 1Mb/s) through the LAN?

Here is my simplified 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();
        }
    }

and 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
    }
Theo
  • 3
  • 2
  • 1
    you are the champ, it was the buffered output :) New speed is 64Mb/s... 1000 times faster! Thanks so much, I've been troubleshooting for days. Can you post it as an answer so that I can accept it? – Theo May 31 '16 at 17:18
  • done, happy to be of help. –  May 31 '16 at 17:20

1 Answers1

0

Either wrap your OutputStream in 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? ; empty TCP packet is 64 bytes, that's 64+1 bytes sent for a 1 byte of data, giving you ~1/65 of the possible transfer rate (YMMV, you may see even higher increase in transfer rates due to getting rid of additional heavy overhead of VM -> OS communication for each single writeByte command).

Rule of thumb for direct 'net transfers is that if you intend to send much less than a usual Ethernet packet (i.e. noticeably less than 1KiB, e.g. 100 bytes) repeatedly over a short time period, it's a good idea to buffer it first and send it collectively.

Community
  • 1
  • 1