THIER@ORCAD2.dnet.ge.com (05/07/91)
In attempting to run TCP socket transfers between two processes residing in the same SPARCstation host, I am experiencing system lock-up after some number of transfers have taken place (the number of transfers varys; it's usually between 950 and 2850 with 30 ms. intermessage spacing). Message sizes are 4446 octets. System configuration is: SPARCstation 1+ SunOS 4.1 GENERIC Kernel. 16 MB memory. 210 MB disk. 56MB swap. Send/Receive Queues = 4096 I appear to be running out of some system resource that is reclaimed after time, as the transfers can be extended somewhat by stopping the transmit process prior to the lockup, waiting awhile, then restarting. I've tried upping MAXUSERS to 16, with no effect. pstat -s shows no appreciable inpact on swap, just prior to the lockup. Netstat shows the many closing connections in TIME_WAIT, but nothing that seems wrong. A typical netstat -m (at the 750 message mark) shows: 244/448 mbufs in use: 7 mbufs allocated to packet headers 96 mbufs allocated to socket structures 135 mbufs allocated to protocol control blocks 2 mbufs allocated to routing table entries 2 mbufs allocated to socket names and addresses 2 mbufs allocated to interface addresses 0/16 cluster buffers in use 72 Kbytes allocated to network (42% in use) 0 requests for memory denied 0 requests for memory delayed 0 calls to protocol drain routines streams allocation: cumulative allocation current maximum total failures streams 11 11 193 0 queues 38 38 508 0 mblks 15 39 57043 0 dblks 15 39 57043 0 streams buffers: external 0 0 0 0 within-dblk 0 4 29675 0 size <= 16 1 25 25725 0 size <= 32 0 3 1256 0 size <= 128 14 16 387 0 size <= 512 0 0 0 0 size <= 1024 0 0 0 0 size <= 2048 0 0 0 0 size <= 8192 0 0 0 0 size > 8192 0 0 0 0 Any insight into what I'm doing wrong would be GREATLY appreciated (see source below). TIA. /* SERVER PROGRAM -------------- This routine creates a TCP socket and binds to the port number given from argv [1]. It executes the following functional loop: Create Connection Socket Fetch Port Number from command line. BIND Connection Socket to port. LISTEN for connections. Loop: Test for connections with SELECT. ACCEPT Connection. Test for Data with SELECT. Loop until 4446 bytes received: RECV data. End Loop; End Loop; For every fifty complete messages received, the current message count is printed to the screen. */ #include <sys/types.h>; #include <sys/time.h>; #include <sys/socket.h>; #include <stdio.h>; #include <netdb.h>; #include <netinet/in.h>; #include <sys/uio.h>; #include <strings.h>; #include <stdio.h>; main(argc, argv) int argc; char *argv[]; { #define BUFFER_SIZE 0xb000 #define COUNT 50 extern errno; int server_sd; int msg_sd; int char_count = 9; char buf[BUFFER_SIZE]; int rx_port; int message_count; int last_count; int selectability; char hostname[7]; int octets_received; struct timeval *timeptr; fd_set readmask; fd_set writemask; fd_set exceptmask; struct sockaddr_in server; struct hostent *server_ent; /******************/ /* Initialization */ /******************/ FD_ZERO (&writemask); FD_ZERO (&exceptmask); timeptr = 0; message_count = 0; last_count = 0; /*********************************************/ /* Create and name Server INET STREAM socket */ /*********************************************/ printf ("\n\n\Server: Creating INET STREAM socket.\n\n"); server_sd = socket(AF_INET, SOCK_STREAM, 0); if (server_sd == -1) { perror("Server: Error creating socket."); } else { sprintf (hostname,"loghost"); server_ent = gethostbyname (hostname); if (server_ent == 0) { perror("Server: Unknown host."); } else { printf("\n\Server: Hostname is %s\n",server_ent->h_name); /**************************/ /* Bind Address to Socket */ /**************************/ bzero( (char *)&server, sizeof(server)); server.sin_family = server_ent -> h_addrtype; bcopy ( (char *)server_ent -> h_addr, (char *)&server.sin_addr, server_ent -> h_length); printf("\n\Server: Internet Address is %s",inet_ntoa(server.sin_addr)); rx_port = atoi( argv[1] ); server.sin_port = (short)rx_port; printf ("\n\n\Server: Local Port Number is %i\n\n",server.sin_port); if (bind (server_sd, (struct sockaddr_in *)&server, sizeof(struct sockaddr_in) ) == -1) { perror("Server: Error binding socket"); } else { printf ("\n\n\Server: Socket bound to name 'server_sock'\n\n"); /***************************/ /* Listen for Connections */ /***************************/ listen(server_sd, 5); printf ("\n\n\Server: Listening for connection.\n\n"); /************************/ /* Execute Receive Loop */ /************************/ while (1) { /*******************************/ /* Pend on Connection Attempt. */ /*******************************/ FD_ZERO (&readmask); FD_SET (server_sd, &readmask); selectability = select (FD_SETSIZE, &readmask, &writemask, &exceptmask, timeptr); if (selectability > 0) { if FD_ISSET (server_sd, &readmask) { msg_sd = accept (server_sd, (struct sockaddr_in *)0, sizeof(struct sockaddr_in) ); if (msg_sd == -1) { perror("Server: Error accepting connection"); } else { /*****************/ /* Pend on Data. */ /*****************/ FD_ZERO (&readmask); FD_SET (msg_sd, &readmask); selectability = select (FD_SETSIZE, &readmask, &writemask, &exceptmask, timeptr); if (selectability > 0) { if FD_ISSET (msg_sd, &readmask) { message_count = message_count + 1; octets_received = 0; while (octets_received < 4446) { char_count = 1; char_count = recv(msg_sd, buf, BUFFER_SIZE, 0); if (char_count == -1) { perror("Server: Error receiving data."); }; /* End RECV Check */ octets_received = octets_received + char_count; }; /* End Receive Loop. */ close (msg_sd); if (message_count - last_count == COUNT) { printf ("\n\n%i", message_count); printf ("\ messages received.\n\n"); last_count = message_count; }; /* End Periodic Message. */ }; /* End Data Readability Check. */ } else { perror("Server: Error on Data Select."); }; /* End Data Select Check. */ }; /* End Accept Check */ }; /* End Connection Check. */ }; /* End Connection Select Check. */ }; /* End Input Loop */ close (server_sd); }; /* End Bind Check */ }; /* End Gethostname conditional */ }; /* End Socket Create Conditional */ printf ("\n\n\Server: Terminating.\n\n"); exit(); } /* end main */ /* CLIENT PROGRAM -------------- This routine creates a TCP socket and connects to the host and port given from argv [1] and [2], respectively. It executes the following functional loop: Fetch Server hostname and port number from command line. Loop for CONNECTION_LOOPS (currently set to 3000): Create socket. CONNECT to Server. Test for writability of socket with SELECT. SEND data (4446 bytes of ASCII 5's). Close socket. End Loop; */ #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <netdb.h> #include <netinet/in.h> #include <fcntl.h> #include <stdio.h> #include <sys/time.h> main(argc, argv) int argc; char *argv[]; { #define BUFFER_SIZE 4446 #define CONNECTION_LOOPS 3000 extern errno; int client_sd; int output_cnt; int i; int cntd; int rx_port; int selectability; int unix_call_status; struct timeval current_time; struct timeval previous_time; struct timezone system_time_zone; long delta_seconds; long delta_microseconds; struct sockaddr_in server; struct sockaddr_in client; struct hostent *server_ent; struct hostent *client_ent; char buf_out[BUFFER_SIZE]; char hostname[25]; fd_set readmask; fd_set writemask; fd_set exceptmask; struct timeval timeout; /******************/ /* Initialization */ /******************/ for (i = 0; i < BUFFER_SIZE; i++) { buf_out[i] = '5'; }; cntd = 1; FD_ZERO (&readmask); FD_ZERO (&exceptmask); timeout.tv_sec = 2; timeout.tv_usec = 0; system_time_zone.tz_minuteswest = 0; system_time_zone.tz_dsttime = DST_GB; /********************************************/ /* Fetch Client Host Data from '/etc/hosts '*/ /********************************************/ sprintf (hostname,"loghost"); client_ent = gethostbyname (hostname); if (client_ent == 0) { perror("Client: Unknown local host."); } else { printf("\n\Client: Hostname is %s\n",client_ent->h_name); printf("\n\Alias is %s\n",*((char *)client_ent->h_aliases)); /*******************************************************/ /* Load Client Socket Structure with Host information. */ /*******************************************************/ bzero( (char *)&client, sizeof(client)); client.sin_family = client_ent -> h_addrtype; printf ("\n\Client: Domain Type is %i\n\n",client.sin_family); bcopy ( (char *)client_ent -> h_addr, (char *)&client.sin_addr, client_ent -> h_length); printf("\n\Client: Internet Address is %s",inet_ntoa(client.sin_addr)); /*********************************************************/ /* Load Client Socket Structure with Server information. */ /*********************************************************/ server_ent = gethostbyname (argv[1]); if (server_ent == 0) { perror("Client: Unknown server host."); } else { printf("\n\Client: Server hostname is %s\n",server_ent->h_name); bzero( (char *)&server, sizeof(server)); server.sin_family = server_ent -> h_addrtype; bcopy ( (char *)server_ent -> h_addr, (char *)&server.sin_addr, server_ent -> h_length); printf("\n\Client: Server Address is %s",inet_ntoa(server.sin_addr)); rx_port = atoi(argv[2]); server.sin_port = (short)rx_port; printf ("\n\n\Client: Server Port Number is %i\n\n",server.sin_port); /********************************/ /* Commence Connect & Send Loop */ /********************************/ /**********************/ /* Connect to Server. */ /**********************/ for (i = CONNECTION_LOOPS; ( (0 < i) && (cntd != 0) ); i--) { /************************/ /* Create client socket */ /************************/ if ( (client_sd = socket(AF_INET, SOCK_STREAM, 0) ) == -1) { perror("Client: Error creating socket."); } else { /****************************/ /* Connect to parent socket */ /****************************/ cntd = connect (client_sd, (struct sockaddr_in *)&server, sizeof (struct sockaddr_in) ); if (cntd == -1) { perror("Client: Error connecting to Server"); printf("\n%i\n",errno); } else { /***************************************************/ /* Test Writability of Socket for up to 2 Seconds. */ /***************************************************/ FD_ZERO (&writemask); FD_SET (client_sd, &writemask); selectability = select (FD_SETSIZE, &readmask, &writemask, &exceptmask, &timeout); if (selectability > 0) { if FD_ISSET (client_sd, &writemask) { /*************************/ /* Write data to socket. */ /*************************/ output_cnt = send (client_sd, buf_out, sizeof(buf_out), 0); if (output_cnt == -1) { perror("Client: Error sending data."); } else { /* sprintf(print_buf_1, "Client: Output buffer transmitted.");*/ }; /* End Send Confirmation. */ }; /* End Writability Check. */ } else if (selectability == 0) { printf ("\n\n\Select Timeout.\n\n"); } else { printf ("\n\n\Select Failure.\n\n"); }; /* End Select Confirmation */ }; /* End Connect Confirmation. */ /****************/ /* Close Socket */ /****************/ close (client_sd); cntd = 1; }; /* End Socket Create Confirmation. */ /**********************/ /* Intermessage Delay */ /**********************/ delta_microseconds = 0; unix_call_status = gettimeofday (&previous_time, &system_time_zone); while (delta_microseconds < 30000) { unix_call_status = gettimeofday (¤t_time, &system_time_zone); delta_seconds = current_time.tv_sec - previous_time.tv_sec; delta_microseconds = current_time.tv_usec - previous_time.tv_usec; if (delta_seconds < 5) { delta_microseconds = (delta_seconds*1000000) + delta_microseconds; }; }; }; /* End Transmission Loop. */ }; /* End Remote Host conditional. */ }; /* End Local Host conditional. */ printf ("\n\n\Client: Terminating.\n\n"); perror("Errno is "); exit (0); } John Thier GE Defense Systems Division Pittsfield MA thier@orcad2.dnet.ge.com