PageRenderTime 45ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/ClassMaster2014/barahon/Transcend_0.3_UnixSource/minorGems/network/linux/socketSelectAcceptBug.cpp

https://gitlab.com/garheade/linux_camp
C++ | 151 lines | 71 code | 54 blank | 26 comment | 13 complexity | 5a82b8f0fa9ff3713406a01dbf9572a5 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. /*
  2. * Demonstration of "accept after select" socket bug.
  3. *
  4. * This program works fine on:
  5. * LinuxPPC, FreeBSD, and MacOSX
  6. *
  7. * This program does not work on:
  8. * LinuxX86 Kernel 2.4
  9. * (accept fails after select returns)
  10. *
  11. * This bug has something to do with the size of the
  12. * variables on the stack...
  13. * Getting rid of the union (which is unnecessary) seems
  14. * to fix the problem.
  15. *
  16. *
  17. * Jason Rohrer
  18. * 2002-April-12
  19. * rohrer@cse.ucsc.edu
  20. */
  21. #include <sys/types.h>
  22. #include <sys/time.h>
  23. #include <unistd.h>
  24. #include <sys/socket.h>
  25. #include <netinet/in.h>
  26. #include <stdio.h>
  27. #include <errno.h>
  28. #include <stdlib.h>
  29. union sock {
  30. struct sockaddr s;
  31. struct sockaddr_in i;
  32. } sock;
  33. void usage( char *inAppName );
  34. int acceptConnection( int inSocketID, long inTimeoutMS );
  35. int port;
  36. int main( int inNumArgs, char **inArgs ) {
  37. if( inNumArgs != 2 ) {
  38. usage( inArgs[0] );
  39. }
  40. int numRead = sscanf( inArgs[1], "%d", &port );
  41. // create a socket and start listening for connections
  42. printf( "Creating socket\n" );
  43. int socketID = socket( AF_INET, SOCK_STREAM, 0 );
  44. if( socketID == -1 ) {
  45. printf( "Socket creation failed\n" );
  46. exit( 1 );
  47. }
  48. // bind socket to the port
  49. union sock sockAddress;
  50. sockAddress.i.sin_family = AF_INET;
  51. sockAddress.i.sin_port = htons( port );
  52. sockAddress.i.sin_addr.s_addr = INADDR_ANY;
  53. printf( "Binding to socket at port %d\n", port );
  54. int error = bind( socketID, &(sockAddress.s), sizeof( struct sockaddr ) );
  55. if( error == -1 ) {
  56. printf( "Bad socket bind, port %d\n", port );
  57. exit( 1 );
  58. }
  59. // start listening for connections, max queued = 100 connections
  60. printf( "Starting to listen to socket\n" );
  61. error = listen( socketID, 100 );
  62. if( error == -1 ) {
  63. printf( "Bad socket listen\n" );
  64. exit(1);
  65. }
  66. // no we're listening to this socket
  67. int acceptedID = acceptConnection( socketID, 50000 );
  68. if( acceptedID != -1 ) {
  69. // close the connection
  70. shutdown( acceptedID, SHUT_RDWR );
  71. close( acceptedID );
  72. }
  73. shutdown( socketID, SHUT_RD );
  74. return 1;
  75. }
  76. int acceptConnection( int inSocketID, long inTimeoutMS ) {
  77. // use select to timeout if no connection received in 10 seconds
  78. struct timeval tv;
  79. socklen_t addressLength;
  80. union sock acceptedAddress;
  81. int acceptedID = accept( inSocketID,
  82. &( acceptedAddress.s ), &addressLength );
  83. if( acceptedID == -1 ) {
  84. printf( "Failed to accept the connection\n" );
  85. printf( "Error = %d\n", errno );
  86. return -1;
  87. }
  88. else {
  89. printf( "Successfully accepted the connection\n" );
  90. return acceptedID;
  91. }
  92. }
  93. void usage( char *inAppName ) {
  94. printf( "Usage:\n" );
  95. printf( " %s port_number\n", inAppName );
  96. exit( 1 );
  97. }