int main(int argc, char **argv) { int motors_socket; int listen_socket; int client_socket; int rc; rc = parse_switches(argc, argv); if (rc < 0) { usage(argv[0]); goto error; } listen_socket = server_start(listen_port); if (listen_socket < 0) { fprintf(stderr, "server_start returned exit status %d\n", listen_socket); goto error; } motors_socket = connect_to_server(motors_ip, motors_port); if (motors_socket < 0) { fprintf(stderr, "connect_to_server returned exit status %d\n", errno); goto error; } if (verbose) { printf("Connected to motors-rpi\n"); } while (1) { client_socket = server_get_connection(listen_socket); main_loop(client_socket, motors_socket); close(client_socket); } close(listen_socket); return EXIT_SUCCESS; error: return EXIT_FAILURE; }
int main(int argc, char *argv[]) { char buff[BUFLEN], sysbuff[2*BUFLEN]; short *ptr; int rval, option; int verbose = 0; // Disable printing message int iteration; // Iteration of receiving/sending int test_mode; // Test mode (RTT/Throughput) int stream_mode; // Stream or ping-pong mode int CPUoption; // Monitor system information? long_int size; // Message size long_int elapsedTime; // Elapsed time struct SYSInfo sysinfo; // Structure for system information struct PROInfo proinfo; // Structure for process information struct hostent *hp; // Hostent structure struct in_addr sin_addr; // Hold client's address /**************** Variable initialization ******************************/ /******* 0 means using default value in the socket option setting ******/ controlSock.port = DEFAULTPORT; // TCP connection port number controlSock.recvBuf = 0; // TCP socket (recv) buffer size controlSock.sendBuf = 0; // TCP socket (send) buffer size controlSock.blocking = 1; // Blocking communication mode controlSock.delay = 0; // Enable Nagel algorithm controlSock.mss = 0; // TCP MSS (Maximum Segment Size) controlSock.cork = 0; // TCP_CORK option controlSock.tos =0; // TOS (Type of Service) controlSock.dataSize = 8192; // Data size of each sending/receiving testSock.port = 0; // Test port is selected by system /*********************** Print help message ****************************/ if ( argc > 1 && strcmp(argv[1], "--help") == 0 ) { fprintf(stderr, help_description); fprintf(stderr, help_usage, DEFAULTPORT, DEFAULTSIZE, DEFAULTPORT, DEFAULTREPEAT, DEFAULTTIME); fprintf(stderr, help_example); return 0; } /**************** Parse the command line *******************************/ if ( argc > 1 ) { while ( (option = getopt (argc, argv, ":vp:")) != -1) { switch ( option ) { case 'v': verbose = 1; break; case 'p': if ( atoi(optarg) >= 0 ) controlSock.port = atoi(optarg); break; case ':': fprintf(stderr,"Error: -%c without filename.\n", optopt); print_usage(); return 1; case '?': fprintf(stderr,"Error: Unknown argument %c\n", optopt); print_usage(); return 1; default: print_usage(); return 1; } } } /******************** Handle the interruption **************************/ signal(SIGINT, int_sig_handler); signal(SIGTSTP, int_sig_handler); signal(SIGPIPE, pipe_sig_handler); signal(SIGCHLD, child_sig_handler); /************ Initialize communications for the server *****************/ if ( server_init(&controlSock) == NOTOK) { perror("Unable to initialize communications."); exit(1); } fprintf(stderr, "TCP socket listening on port [%d]\n", controlSock.port); /**************** TCP data channel waiting a connection ****************/ while ( server_get_connection(&controlSock, &sin_addr) == OK ) { /********** Create a new process to handle the UDP test ************/ if ( (rval=fork()) > 0 ) { // Parent close (controlSock.socket); continue; } else // Child close (controlSock.welcomeSocket); /*** Receive the TCP communication options from client *************/ bzero(buff, BUFLEN); if ( get_request(&controlSock, buff) == NOTOK || sscanf(buff, client_request_str, &test_mode, &testSock.blocking, &testSock.delay, &testSock.cork, &stream_mode, &testSock.recvBuf, &testSock.sendBuf, &testSock.mss, &testSock.tos, &testSock.dataSize, &CPUoption) != 11 ) { if ( verbose ) { fprintf(stderr, "Receive TCP options error [%s]\n", buff); fprintf(stderr, "Quit this session.\n"); } close (controlSock.socket); exit (1); } if ( CPUoption ) { if ( start_trace_system( &sysinfo ) == OK ) { sleep (1); if ( stop_trace_system ( &sysinfo ) == OK ) CPUoption = 1; } else CPUoption = 0; } /************************ Check the test mode **********************/ if ( test_mode != LATENCY && test_mode != SENDFILE && test_mode != THROUGHPUT ) { if ( verbose ) fprintf(stderr, "Wrong test mode request: %d\n", test_mode); close (controlSock.socket); exit (1); } /********** Create another TCP connection (test channel) **********/ if ( server_init(&testSock) == NOTOK ) { if ( verbose ) fprintf(stderr, "Server test channel initialization error. \n"); close (controlSock.socket); exit(1); } /********* Allocate the memory for sending/receiving data **********/ if ( (rbuffer = (char *)malloc(testSock.dataSize)) == NULL || (sbuffer = (char *)malloc(testSock.dataSize)) == NULL ) { if ( verbose ) fprintf(stderr, "Could not malloc memory! buffer size: %lld\n", size); close (controlSock.socket); exit(1); } /**** Randomize the buffer to prevent possible data compression ****/ srand(time(NULL)); for ( ptr = (short *)sbuffer; ptr < (short *)(sbuffer+testSock.dataSize); ptr +=2 ) *ptr = (short)rand(); /******** Inform client the test channel's port number *************/ sprintf(buff, server_port_str, testSock.port); if ( send_request(controlSock.socket, buff, strlen(buff)) == NOTOK ) { if ( verbose ) fprintf(stderr, "Send TCP test port number error.\n"); close_session(); } /************ Accept (establish) the test connection ***************/ if ( server_get_connection(&testSock, &sin_addr) == NOTOK ) { fprintf(stderr, "Server test channel getting connection error.\n"); close_session(); } close(testSock.welcomeSocket); // Close test channel's welcome socket /*********** Inform client the server's network settings ***********/ sprintf(buff, server_parameter_str, testSock.blocking, testSock.delay, testSock.cork, testSock.recvBuf, testSock.sendBuf, testSock.mss, testSock.tos, CPUoption); if ( send_request(controlSock.socket, buff, strlen(buff)) == NOTOK ) { if ( verbose ) fprintf(stderr, "Failed to send server's configuration.\n"); close_session(); } /********** Send syslog to client if the option is defined *********/ if ( CPUoption ) { bzero(sysbuff, 2*BUFLEN); if ( sysinfo_to_string(&sysinfo, sysbuff, 2*BUFLEN) == NOTOK || send_request(controlSock.socket, sysbuff, strlen(sysbuff)) == NOTOK ) { if ( verbose ) fprintf(stderr, "Failed to send system initial information.\n"); close_session(); } } /*********** Print out the connection message **********************/ if ( verbose ) { get_local_time(buff, BUFLEN); fprintf(stderr, "Session[%d] started at [%s]:\n", (int)getpid(), buff); if ( (hp=gethostbyaddr((char *)&sin_addr, sizeof(sin_addr), AF_INET)) ) fprintf(stderr, "Connection from %s [%s] ", hp->h_name, inet_ntoa(sin_addr)); else // Host not in the host tables or DNS fprintf(stderr, "Connection from [%s] ", inet_ntoa(sin_addr)); if ( test_mode == SENDFILE ) strcpy(buff, "Throughput test with sendfile"); else strcpy(buff, test_mode == LATENCY ? "Latency(RTT) test":"Throughput test"); fprintf(stderr, "[%s] [%s]\n", buff, stream_mode ? "Unidirectional":"Bidirectional"); fprintf(stderr, "%s %s %s ", testSock.blocking ? "Blocking[ON]":"Blocking[OFF]", testSock.delay ? "TCP_NODELAY[OFF]":"TCP_NODELAY[ON]", testSock.cork ? "TCP_CORK[ON]":"TCP_CORK[OFF]"); fprintf(stderr, "Recv-buff[%d] Send-buff[%d] MSS[%d]\n", testSock.recvBuf, testSock.sendBuf, testSock.mss); } /** Set a timer in case of communication abnormally disconnected ***/ if ( signal(SIGALRM, time_out_handler) == SIG_ERR ) { if ( verbose ) perror("Signal alarm."); close_session(); } if ( setjmp(alarm_env) != 0 ) { if ( verbose ) fprintf(stderr, "Connection lost.\n"); close_session(); } alarm (5); /********** TCP test channel waiting for a request ****************/ while ( get_request(&controlSock, buff) == OK ) { alarm(0); // Cancel timer /********************** parse client's request *****************/ if ( sscanf(buff, test_start_str, &size, &iteration) != 2) { /************************* Session ends ********************/ if ( strncmp(buff, test_done_str, strlen(test_done_str)) == 0 ) { if ( test_mode != LATENCY && CPUoption ) { if ( start_trace_system(&sysinfo) == OK ) { sleep(1); bzero(buff, BUFLEN); if ( stop_trace_system(&sysinfo) == OK && sysinfo_to_string( &sysinfo, sysbuff, 2*BUFLEN ) == OK && send_request(controlSock.socket, sysbuff, strlen(sysbuff)) == OK ) { if ( verbose ) { get_local_time(buff, BUFLEN); fprintf(stderr, "Session[%d] ended at [%s].\n", (int)getpid(), buff); } close_session(); } } if ( verbose ) fprintf(stderr, "Failed to send the last syslog.\n"); } if ( verbose ) { get_local_time(buff, BUFLEN); fprintf(stderr, "Session[%d] ended at [%s].\n", (int)getpid(), buff); } close_session(); } else if ( verbose ) fprintf(stderr, "Wrong format. Unable to parse request: %s", buff); close_session(); } /************** Are request number acceptable? *****************/ if ( size < 1 || iteration < 1 ) { if ( verbose ) fprintf(stderr, "Client's request is not acceptable...\n"); close_session(); } if ( CPUoption ) { if( start_trace_system( &sysinfo ) == NOTOK ) { if ( verbose ) fprintf(stderr, "Trace system information error.\n"); close_session(); } } if ( test_mode != LATENCY ) start_trace_process( &proinfo ); if ( (server_tcp_test(size, iteration, stream_mode, &elapsedTime, &testSock)) == NOTOK ) { if ( verbose ) fprintf(stderr, "TCP test error. Quit the session.\n"); close_session(); } else { if ( test_mode != LATENCY ) stop_trace_process( &proinfo ); // Stop tracing process info if ( CPUoption ) { // Stop tracing system info usleep(1000); // Wait for a while for the data to be updated if ( stop_trace_system ( &sysinfo ) == NOTOK ) { if ( verbose ) fprintf(stderr, "Failed to get system information.\n"); } } strcpy(buff, test_done_str); // Send a confirmation to client if ( send_request(controlSock.socket, buff, strlen(buff)) == NOTOK ) { if ( verbose ) fprintf(stderr, "Failed to send confirmation error\n"); close_session(); } if ( test_mode != LATENCY ) { // Send the process inforamtion sprintf(buff, server_proinfo_str, elapsedTime, proinfo.utime_sec*1000000LL + proinfo.utime_usec, proinfo.stime_sec*1000000LL + proinfo.stime_usec); if ( send_request(controlSock.socket, buff, strlen(buff)) == NOTOK ) { if ( verbose ) fprintf(stderr, "Failed to send process info error\n"); close_session(); } } if ( CPUoption ) { // Send client the system information if defined if ( sysinfo_to_string( &sysinfo, sysbuff, 2*BUFLEN) == NOTOK || send_request(controlSock.socket, sysbuff, strlen(sysbuff)) == NOTOK ) { if ( verbose ) fprintf(stderr, "Failed to send system information.\n"); close_session(); } } } #ifdef DEBUG fprintf(stderr, " DEBUG: Test done in %s mode. Message size: %lld Repeats: %d \n", stream_mode ? "stream":"ping-pong", size, iteration); if ( elapsedTime > 0 ) fprintf(stderr, " DEBUG: Total transimitted %lld bytes in %f seconds. Network throughput : %f Mbps\n\n", stream_mode? size*iteration : size*2*iteration, elapsedTime/1000000.0, stream_mode ? size*iteration*8.0/elapsedTime : size*iteration*2*8.0/elapsedTime ); #endif } // while loop of get_request close_session(); } // while loop of get_connection /*********************** clean up the connections. *********************/ server_shutdown(); return 0; }