1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
|
/*
* Demonstration of "accept after select" socket bug.
*
* This program works fine on:
* LinuxPPC, FreeBSD, and MacOSX
*
* This program does not work on:
* LinuxX86 Kernel 2.4
* (accept fails after select returns)
*
* This bug has something to do with the size of the
* variables on the stack...
* Getting rid of the union (which is unnecessary) seems
* to fix the problem.
*
*
* Jason Rohrer
* 2002-April-12
* rohrer@cse.ucsc.edu
*/
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
union sock {
struct sockaddr s;
struct sockaddr_in i;
} sock;
void usage( char *inAppName );
int acceptConnection( int inSocketID, long inTimeoutMS );
int port;
int main( int inNumArgs, char **inArgs ) {
if( inNumArgs != 2 ) {
usage( inArgs[0] );
}
int numRead = sscanf( inArgs[1], "%d", &port );
// create a socket and start listening for connections
printf( "Creating socket\n" );
int socketID = socket( AF_INET, SOCK_STREAM, 0 );
if( socketID == -1 ) {
printf( "Socket creation failed\n" );
exit( 1 );
}
// bind socket to the port
union sock sockAddress;
sockAddress.i.sin_family = AF_INET;
sockAddress.i.sin_port = htons( port );
sockAddress.i.sin_addr.s_addr = INADDR_ANY;
printf( "Binding to socket at port %d\n", port );
int error = bind( socketID, &(sockAddress.s), sizeof( struct sockaddr ) );
if( error == -1 ) {
printf( "Bad socket bind, port %d\n", port );
exit( 1 );
}
// start listening for connections, max queued = 100 connections
printf( "Starting to listen to socket\n" );
error = listen( socketID, 100 );
if( error == -1 ) {
printf( "Bad socket listen\n" );
exit(1);
}
// no we're listening to this socket
int acceptedID = acceptConnection( socketID, 50000 );
if( acceptedID != -1 ) {
// close the connection
shutdown( acceptedID, SHUT_RDWR );
close( acceptedID );
}
shutdown( socketID, SHUT_RD );
return 1;
}
int acceptConnection( int inSocketID, long inTimeoutMS ) {
// use select to timeout if no connection received in 10 seconds
struct timeval tv;
socklen_t addressLength;
union sock acceptedAddress;
int acceptedID = accept( inSocketID,
&( acceptedAddress.s ), &addressLength );
if( acceptedID == -1 ) {
printf( "Failed to accept the connection\n" );
printf( "Error = %d\n", errno );
return -1;
}
else {
printf( "Successfully accepted the connection\n" );
return acceptedID;
}
}
void usage( char *inAppName ) {
printf( "Usage:\n" );
printf( " %s port_number\n", inAppName );
exit( 1 );
}
|