Click here to Skip to main content
15,886,199 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I write a demo about communication between windows and linux.

The performance is only 40MB/s under the gigabit network environment.

if I send the entire buffer, the performance will be to 90MB/s. But my work need to send every 64KB data and receive feed back, then send the next 64KB. :-(

Is there any way to upgrade the performance? And I don't know why it so slow.

the code in windows as client
C++
#include "stdafx.h"


#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>


// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")


#define DEFAULT_BUFLEN 65536
#define DEFAULT_PORT "27015"

int tcpnodelay(int sock) {
    int yes=1;
    return setsockopt(sock,IPPROTO_TCP,TCP_NODELAY,(char*)&yes,sizeof(int));
}

int __cdecl main(int argc, char **argv) 
{
    WSADATA wsaData;
    SOCKET ConnectSocket = INVALID_SOCKET;
    struct addrinfo *result = NULL,
                    *ptr = NULL,
                    hints;
    char sendbuf[DEFAULT_BUFLEN];
    char recvbuf[32];
    unsigned long no;
    unsigned long iResult;
    unsigned long sent;
    int recvbuflen = 32;
    int recv_len, n;
    unsigned long recv_no;

    // Validate the parameters
    if (argc != 2) {
        printf("usage: %s server-name\n", argv[0]);
        return 1;
    }

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed with error: %d\n", iResult);
        return 1;
    }

    ZeroMemory( &hints, sizeof(hints) );
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    // Resolve the server address and port
    iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
    if ( iResult != 0 ) {
        printf("getaddrinfo failed with error: %d\n", iResult);
        WSACleanup();
        return 1;
    }

    // Attempt to connect to an address until one succeeds
    for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {

        // Create a SOCKET for connecting to server
        ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, 
            ptr->ai_protocol);
        if (ConnectSocket == INVALID_SOCKET) {
            printf("socket failed with error: %ld\n", WSAGetLastError());
            WSACleanup();
            return 1;
        }

        // Connect to server.
        iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
        if (iResult == SOCKET_ERROR) {
            closesocket(ConnectSocket);
            ConnectSocket = INVALID_SOCKET;
            continue;
        }
        break;
    }

    freeaddrinfo(result);

    if (ConnectSocket == INVALID_SOCKET) {
        printf("Unable to connect to server!\n");
        WSACleanup();
        return 1;
    }

    if (tcpnodelay(ConnectSocket)<0) {
        printf("Can't set TCP_NODELAY!\n");
    }

    recv_len = sizeof(no);
    printf("recv_len: %d\n", recv_len);

    // Send an initial buffer
    memset(sendbuf, 0, DEFAULT_BUFLEN);
    for (no=0; no<1024*1024; no++) {
        sent = 0;
        while (sent < DEFAULT_BUFLEN) {
            iResult = send(ConnectSocket, sendbuf+sent, DEFAULT_BUFLEN-sent, 0);

            if (iResult == SOCKET_ERROR) {
                printf("send failed with error: %d\n", WSAGetLastError());
                closesocket(ConnectSocket);
                WSACleanup();
                return 1;
            }

            sent += iResult;
        }


        n = recv(ConnectSocket, (char *)(&recv_no), recv_len, 0);
        if (recv_len!=n || recv_no!=no) {
            printf("recv len: %d, recv no %ld", n, recv_no);
            exit(1);
        }

    }


    printf("Bytes Sent: %ld\n", iResult);

    // shutdown the connection since no more data will be sent
    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    // cleanup
    closesocket(ConnectSocket);
    WSACleanup();

    return 0;
}


the code in linux as server
C++
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>

int main( int argc, char *argv[] )
{
  int sockfd, newsockfd, portno, clilen;
  char buffer[65536];
  unsigned int no;
  unsigned long read_size;
  struct sockaddr_in serv_addr, cli_addr;
  int  n;
  int send_len;

  /* First call to socket() function */
  sockfd = socket(AF_INET, SOCK_STREAM, 0);
  if (sockfd < 0) 
  {
    perror("ERROR opening socket");
    exit(1);
  }
  /* Initialize socket structure */
  bzero((char *) &serv_addr, sizeof(serv_addr));
  portno = 27015;
  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = INADDR_ANY;
  serv_addr.sin_port = htons(portno);

  /* Now bind the host address using bind() call.*/
  if (bind(sockfd, (struct sockaddr *) &serv_addr,
           sizeof(serv_addr)) < 0)
  {
    perror("ERROR on binding");
    exit(1);
  }

  /* Now start listening for the clients, here process will
   * go in sleep mode and will wait for the incoming connection
   */
  listen(sockfd,5);
  clilen = sizeof(cli_addr);

  /* Accept actual connection from the client */
  newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, 
                     &clilen);
  if (newsockfd < 0) 
  {
    perror("ERROR on accept");
    exit(1);
  }

  send_len = sizeof(no);
  printf("send_len: %d\n", send_len);

  /* If connection is established then start communicating */
  bzero(buffer,65536);
  for (no=0; no<1024*1024; no++) {
    read_size = 0;
    while (read_size < 65536) {
      n = read( newsockfd,buffer+read_size,65536-read_size );
      if (n < 0)
      {
        perror("ERROR reading from socket");
        exit(1);
      }
      read_size += n;
    }


    n = write(newsockfd, &no, send_len);
    if (n < send_len) {
      printf("send len: %d\n", n);
      exit(1);
    }
  }
  printf("the message size: %d\n", n);

  /* Write a response to the client */
  n = write(newsockfd,"I got your message",18);
  if (n < 0)
  {
    perror("ERROR writing to socket");
    exit(1);
  }

  close(newsockfd);

  return 0; 
}
Posted
Comments
Sergey Alexandrovich Kryukov 25-Oct-13 1:30am    
It's pretty hard to analyze all factors, but it does not sound unusual: when you feed data in smaller chunks, the loss in throughput could be dramatic...
—SA

For each block of data you are sending from the client to the server, your server answers by sending the block number and the client waits for this packet before sending the next block of data. These packets slow down the overall throughput.

You may remove them and send one status message after all blocks has been transferred or to indicate interruptions.
 
Share this answer
 
Comments
mzgcz 26-Oct-13 8:23am    
Yes, you are right! It's a good idea to send my data as long as I can. It can help reduce the packets, and up the speed.
That is pretty normal numbers, see this link : http://www.tomshardware.com/reviews/gigabit-ethernet-bandwidth,2321-3.html[^]
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900