Advertisement
Guest User

Failure case for IOCP which works with select.

a guest
Oct 30th, 2010
128
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.43 KB | None | 0 0
  1. #ifdef _WIN32
  2. #   define WIN32
  3. #endif
  4.  
  5. #include <event2/util.h>
  6. #include <event2/event.h>
  7. #include <event2/buffer.h>
  8. #include <event2/thread.h>
  9. #include <event2/listener.h>
  10. #include <event2/bufferevent.h>
  11.  
  12. #include <assert.h>
  13.  
  14.  
  15. #ifdef _WIN32
  16. #   define WINDOWS_LEAN_AND_MEAN    1
  17. #include <WinSock2.h>
  18. #include <Windows.h>
  19. #endif
  20.  
  21. #define USE_IOCP    0
  22.  
  23.  
  24. struct event_base*  eventBase   =   NULL;
  25.  
  26.  
  27. //**********************************************************************
  28. //  Server side simulation.
  29. //**********************************************************************
  30. void serverReadCallback( struct bufferevent *bev, void *ctx )
  31. {
  32.     (void)bev; (void)ctx;
  33.     struct evbuffer*    input   =   bufferevent_get_input( bev );
  34.     evbuffer_drain( input, evbuffer_get_length( input ) );
  35. }
  36.  
  37.  
  38. void serverWriteCallback( struct bufferevent *bev, void* )
  39. {
  40.     struct evbuffer*    output  =   bufferevent_get_output( bev );
  41.     assert( evbuffer_get_length( output )==0 );
  42.     shutdown( bufferevent_getfd( bev ), SD_SEND );
  43. }
  44.  
  45. void serverEventCallback( struct bufferevent *bev, short what, void *ctx )
  46. {
  47.     (void)bev; (void)what; (void)ctx;
  48.     switch( what )
  49.     {
  50.     case BEV_EVENT_EOF | BEV_EVENT_READING:
  51.         printf( "Server: Read EOF\n" );
  52.         bufferevent_free( bev );
  53.         event_base_loopexit( eventBase, NULL );
  54.         break;
  55.     case BEV_EVENT_EOF | BEV_EVENT_WRITING:
  56.         printf( "Server: Write EOF\n" );
  57.         break;
  58.     }
  59. }
  60.  
  61.  
  62. //**********************************************************************
  63. //  Client side simulation.
  64. //**********************************************************************
  65. void clientReadCallback( struct bufferevent *bev, void * )
  66. {
  67.     // Going to bounce the data back to the server side.
  68.     struct evbuffer*    input   =   bufferevent_get_input( bev );
  69.     struct evbuffer*    output  =   bufferevent_get_output( bev );
  70.     evbuffer_add_buffer( output, input );
  71.     bufferevent_setwatermark( bev, EV_WRITE, 1, 0 );
  72. }
  73.  
  74. void clientWriteCallback( struct bufferevent *bev, void *ctx )
  75. {
  76.     (void)bev; (void)ctx;
  77.     shutdown( bufferevent_getfd( bev ), SD_SEND );
  78. }
  79.  
  80. void clientEventCallback( struct bufferevent *bev, short what, void *ctx )
  81. {
  82.     (void)bev; (void)what; (void)ctx;
  83.     switch( what )
  84.     {
  85.     case BEV_EVENT_EOF | BEV_EVENT_READING:
  86.         printf( "Client: Read EOF\n" );
  87.         bufferevent_free( bev );
  88.         break;
  89.     case BEV_EVENT_EOF | BEV_EVENT_WRITING:
  90.         printf( "Client: Write EOF\n" );
  91.         break;
  92.  
  93.     case BEV_EVENT_CONNECTED:
  94.         printf( "Client: Connected\n" );
  95.         break;
  96.     }
  97. }
  98.  
  99.  
  100. //**********************************************************************
  101. //  Listener callback.
  102. //**********************************************************************
  103. void listenerCallback( struct evconnlistener* el, evutil_socket_t fd, struct sockaddr* addr, int addrLen, void* context )
  104. {
  105.     (void)el;
  106.     (void)addr;
  107.     (void)addrLen;
  108.     (void)context;
  109.  
  110.     struct bufferevent* servEvent   =   bufferevent_socket_new( eventBase, fd, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_THREADSAFE );
  111.  
  112.     // Send some trash data and prepare to shutdown.
  113.     int     trash[]     =   {1, 2, 3, 4};
  114.  
  115.     struct evbuffer*    output  =   bufferevent_get_output( servEvent );
  116.     evbuffer_iovec      ioVec;
  117.     evbuffer_reserve_space( output, sizeof( trash ), &ioVec, 1 );
  118.     ::memcpy( ioVec.iov_base, trash, sizeof( trash ) );
  119.     ioVec.iov_len   =   sizeof( trash );
  120.     evbuffer_commit_space( output, &ioVec, 1 );
  121.  
  122.     bufferevent_setwatermark( servEvent, EV_WRITE, 1, 0 );
  123.     bufferevent_setcb( servEvent, &serverReadCallback, &serverWriteCallback, &serverEventCallback, NULL );
  124.     bufferevent_enable( servEvent, EV_READ | EV_WRITE );
  125. }
  126.  
  127.  
  128.  
  129.  
  130. extern "C"
  131. int main( const int argc, const char** argv )
  132. {
  133.     (void)argc; (void)argv;
  134.     static const int kPort      =   4013;
  135.  
  136.  
  137. #ifdef _WIN32
  138.     WSADATA wsaData;
  139.     if( WSAStartup( MAKEWORD( 2, 2 ), &wsaData )!=0 )
  140.         return -1;
  141. #endif
  142.  
  143. #if _WIN32
  144.     if( evthread_use_windows_threads() != 0 )
  145.         return -1;
  146. #else
  147.     if( evthread_use_pthreads() != 0 )
  148.         return -1;
  149. #endif
  150.  
  151.  
  152.     // Bring up the event base potentially with IOCP.
  153.     struct event_config*    eventConfig =   event_config_new();
  154. #ifdef _WIN32
  155. #   if USE_IOCP
  156.     event_config_set_flag( eventConfig, EVENT_BASE_FLAG_STARTUP_IOCP );
  157. #   endif
  158. #endif
  159.     eventBase       =   event_base_new_with_config( eventConfig );
  160.     event_config_free( eventConfig );
  161.  
  162.  
  163.     // Bring up a local listener.
  164.     struct sockaddr_in  listenAddr;
  165.     ::memset( &listenAddr, 0, sizeof( listenAddr ) );
  166.     listenAddr.sin_addr.s_addr  =   0;
  167.     listenAddr.sin_port         =   htons( 4013 );
  168.     listenAddr.sin_family       =   AF_INET;
  169.  
  170.     struct evconnlistener*  listener    =   evconnlistener_new_bind(
  171.         eventBase,
  172.         &listenerCallback,
  173.         NULL,
  174.         LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE,
  175.         -1,
  176.         (const sockaddr*)&listenAddr,
  177.         sizeof( listenAddr ) );
  178.  
  179.     // Bring up the socket which will connect to listener.
  180.     struct sockaddr_in  connectAddr;
  181.     ::memset( &connectAddr, 0, sizeof( connectAddr ) );
  182.     connectAddr.sin_addr.s_addr =   htonl(0x7f000001);
  183.     connectAddr.sin_port        =   htons( kPort );
  184.     connectAddr.sin_family      =   AF_INET;
  185.  
  186.     struct bufferevent*     clientConnection    =   bufferevent_socket_new( eventBase, -1, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_THREADSAFE );
  187.     bufferevent_socket_connect( clientConnection, (sockaddr*)&connectAddr, sizeof( connectAddr ) );
  188.     bufferevent_setcb( clientConnection, &clientReadCallback, &clientWriteCallback, &clientEventCallback, NULL );
  189.     bufferevent_enable( clientConnection, EV_READ | EV_WRITE );
  190.  
  191.  
  192.     // Run the dispatch.
  193.     while( event_base_dispatch( eventBase )==1 )
  194.         ;
  195.  
  196.     evconnlistener_free( listener );
  197.     event_base_free( eventBase );
  198.     return 0;
  199. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement