/* server1udp.c - a server program that uses the socket interface to udp */ /* THIS FILE IS ADAPTED FROM THE HANDOUT OF CS820 OS PROGRAMMING * THE ORIGINAL AUTHOR SHOULD BE PROF. RUSSELL * MODIFIED BY LIN ON OCT,2001 */ #include #include #ifdef __linux__ #ifndef __USE_BSD #define __USE_BSD #endif #endif #include #include #include #include #include #include #include #include "server.h" #ifdef __osf__ /* on DECUNIX no standard header file contains a prototype for herror() */ /* however, the function is in the standard c library ( libc.a ). */ extern void herror( char * name ); #endif /* on solaris this program must be linked with -lnsl and -lsocket to * load the routines defined in the socket library. also on Solaric * contains a prototype for herror(), but it is NOT defined in the standard c * library. therefore, the separate file herror.c must be compiled and link * too */ #define BUFSIZE 65535 #define MAXAMOUNT 10000000 char data[MAXAMOUNT]; void server( int server_port, char * interface_name, int argc, char * argv[] ) { int iterations, packSeq, n , len, fd; int lastSeq = -1; int packetLoss = 0; struct sockaddr_in address, client; struct hostent * node_ptr; char local_node[ MAXHOSTNAMELEN ]; char * host_name; if ( interface_name == NULL ) { /* default to name of local host node */ if ( gethostname( local_node, MAXHOSTNAMELEN ) < 0 ) { perror( "server1udp gethostname" ); exit( EXIT_FAILURE ); } host_name = local_node; }/* end of if */ else host_name = interface_name; /* get structure for host or local interface that server wants to use */ if ( ( node_ptr = gethostbyname( host_name ) ) == NULL ) { herror( host_name ); exit( EXIT_FAILURE ); }/* end of if */ /* set up internet address structure for the server */ memset( &address, 0, sizeof( struct sockaddr_in ) ); address.sin_family = node_ptr->h_addrtype; /* should be AF_INET */ address.sin_port = htons( server_port ); if ( interface_name == NULL ) address.sin_addr.s_addr = htonl( INADDR_ANY ); /* use any interface */ else memcpy( &address.sin_addr, node_ptr->h_addr, node_ptr->h_length ); /* open an internet udp socket */ if ( ( fd = socket( PF_INET, SOCK_DGRAM, 0 ) ) < 0 ) { perror( "server1udp socket" ); exit( EXIT_FAILURE ); } /* bind this socket to the server's Internet address */ if ( bind(fd, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) < 0 ) { perror( "server1udp bind" ); exit( EXIT_FAILURE ); } /* now find out what local port number was assigned to this server */ len = sizeof( struct sockaddr_in ); if ( getsockname( fd, ( struct sockaddr* )&address, (void*)&len) < 0 ) { perror( "server1udp getsockname" ); exit( EXIT_FAILURE ); } /* we are now successfully established as a udp server */ fprintf(stderr,"server1udp: at port %d on node %s, internet address %s\n\n", ntohs( address.sin_port), node_ptr->h_name, inet_ntoa( address.sin_addr ) ); /* repeatedly read a message from a client, the beginning of each packet * is the UDP packet number. server read the packet number. Compare it to * previous packet number. If the number is not in order, message will * be printed on server stand error * special packet seq: * -2 client begins to send UDP, server init packet seq# and packet loss * -1 client reports "end of transmission". server report packet loss */ for( ; ; ) { len = sizeof( client ); if ( ( n = recvfrom( fd, data, MAXAMOUNT, 0, ( struct sockaddr * ) &client, (void*) &len) )>0 ) { data[ n ] = '\0'; /* make data to a C-string */ sscanf( data, "%d", &packSeq ); /* begin packet of new transmision */ if ( packSeq == -2 ) { lastSeq = -1; packetLoss = 0; continue; } /* end packet of this transmission */ if ( packSeq == -1 ) { sscanf( data, "%d%d", &packSeq, &iterations ); if ( iterations != lastSeq + 1 ) { packetLoss += iterations - lastSeq - 1; fprintf(stderr," %d packets lost here\n", iterations - lastSeq - 1 ); } fprintf(stderr,"Expected to receive %d UDP packet.",iterations); fprintf(stderr," Lost %d packets \n", packetLoss ); fprintf(stderr,"\n\n"); lastSeq = -1; packetLoss = 0; continue; } if ( packSeq == lastSeq + 1 ) { lastSeq = packSeq; continue; } /* packet should arrive before */ if ( packSeq < lastSeq ) { fprintf(stderr,"UDP packet %d is out of order,", packSeq ); fprintf(stderr, "should arrive before\n"); packetLoss --; continue; } /* packets lost here */ if ( packSeq > lastSeq + 1 ) { packetLoss += packSeq - lastSeq - 1; fprintf(stderr,"UDP packet %d is out of order.",packSeq); fprintf(stderr,"%d packets lost here\n",packSeq-lastSeq-1 ); lastSeq = packSeq; continue; } fprintf( stderr, "Error: should not arrive here\n"); }/* end of if */ else if ( n < 0 ) { perror( "udpserver recvfrom" ); exit( EXIT_FAILURE ); }/* end of else if */ }/* end of for */ /* close the socket over which server read messages */ if ( close(fd) < 0 ) { perror( "server1udp close"); exit( EXIT_FAILURE ); } }/* end of server */