Thread: WSAAsyncSelect Socket Model. She's Not Hot.

  1. #1
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465

    WSAAsyncSelect Socket Model. She's Not Hot.

    I am trying to code a simple client server application using the WSAAsyncSelect socket model. It is giving me some troubles that may best be described 'screwed up'. I connect to the loopback address with my client, and I get an FD_CONNECT and FD_WRITE notifications, but my server gets nothing! It's hard to be succinct about this problem, so I'm giving three tiers of information: what I see to be the problem, the main source files, and both the client and server projects.

    In my client I do something like:

    Code:
                ADDRINFOT * result = 0, hints = { 0 };
    
                hints.ai_family = AF_UNSPEC;
                hints.ai_socktype = SOCK_STREAM;
                hints.ai_protocol = IPPROTO_TCP;
    
                ret = ::GetAddrInfo( TEXT("127.0.0.1"), 
                    TEXT("4337"), &hints, &result );
    
                ...
    
    
                ret = ::WSAAsyncSelect( sock, window, WM_SOCKET,
                    FD_CONNECT | FD_READ | FD_WRITE | FD_CLOSE );
    
                ret = connect( sock, result->ai_addr, sizeof(sockaddr) );
                if( ret == SOCKET_ERROR && ::WSAGetLastError() != WSAEWOULDBLOCK )
                {
                    // cleanup
                    return -1;
                }
    And then just print a 'howdy-doody' if I get my 'WM_SOCKET' message (which I get on FD_CONNECT and for FD_WRITE). In my server, I do something like:

    Code:
        bool addrResult = false;
    
        sockaddr_in * us;
        SOCKET listener;
    
        ADDRINFOT * result = 0, hints = { 0 };
    
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_protocol = IPPROTO_TCP;
        hints.ai_flags = AI_PASSIVE;
    
        ret = ::GetAddrInfo( NULL, TEXT("4337"), &hints, &result );
        if( ret != 0 )
        {
            dout << ErrorMessage( TEXT("WinMain"), ret ) << TEXT("\n");
    
            us = new sockaddr_in;
    
            us->sin_addr.S_un.S_addr = inet_addr( "127.0.0.1" );
            us->sin_family = AF_INET;
            us->sin_port = htons( static_cast< u_short >( 4337 ) );
            
            listener = ::WSASocket
                ( AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, 0 );
        }
        else
        {
            us = (sockaddr_in *) result->ai_addr;
    
            listener = ::WSASocket
                ( result->ai_family, result->ai_socktype, 
                result->ai_protocol, 0, 0, 0 );
    
            addrResult = true;
        }
    
        ret = ::bind( listener, reinterpret_cast< sockaddr * >(us), sizeof(*us) );
    
        ret = ::WSAAsyncSelect( listener, window->getHwnd(), WM_LISTENING,
            FD_CONNECT | FD_READ | FD_WRITE | FD_CLOSE );
    
        ret = ::listen( listener, 10 );
    And again give myself a howdy-doody if I get a WM_LISTENING message. I never recieve one! My server program gives no debug output or indication of an error (I do extensive checking for errors in the real source), yet my client thinks it's connected (recieves FD_CONNECT and FD_WRITE notifications. I can WSASend successfully on FD_WRITE, but it does no good)! Does anyone know what could be going on?

    Source and stuff to assist you:

    http://zxcvbn.t35.com/ServerMain.cpp
    http://zxcvbn.t35.com/ClientMain.cpp

    http://zxcvbn.t35.com/Server.zip
    http://zxcvbn.t35.com/Client.zip

  2. #2
    Registered User
    Join Date
    Mar 2005
    Location
    Juneda
    Posts
    291
    Hi, I'm not sure about that, but don't you have to set the 'WM_SOCKET_NOTIFY' flag to the 'WSAAsyncSelect()' function to work with the 'FD_CONNECT' and 'FD_WRITE' notifications?

    Code:
    ret = ::WSAAsyncSelect( listener, window->getHwnd(), WM_LISTENING,
    FD_CONNECT | FD_READ | FD_WRITE | FD_CLOSE | WM_SOCKET_NOTIFY );
    Niara

  3. #3
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    I honestly cannot tell what the magic was that fixed it, but that wasn't it, and I can't even tell by looking at a diff of that old revision and the new revision - which I'm going to dump here if anyone happens across this and is making the same silly mistake I did.

    Code:
    1,2d0
    < // Server - Main.cpp
    < 
    6,7c4
    < #include "CWindow.h"
    < #include "CError.h"
    ---
    > #include "WindowStuff.h"
    10c7
    < #include <memory>
    ---
    > #include <sstream>
    19,36d15
    < LPCTSTR ErrorMessage( LPCTSTR func, DWORD err ) 
    < { 
    <     PVOID szBuf;
    < 
    <     DWORD ret = ::FormatMessage
    <         ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
    <         NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    <         (LPTSTR) &szBuf, 0, NULL );
    <  
    <     if( ret == 0 )
    <     {
    <         return TEXT("Something has failed");
    <     }
    < 
    <     return (LPCTSTR) szBuf;
    < }
    < 
    < 
    38a18
    > 
    45c25
    <         dout << ErrorMessage( TEXT("WinMain"), ::WSAGetLastError() ) << TEXT("\n");
    ---
    >         dout << geterr( TEXT("WinMain"), ::WSAGetLastError() ) << TEXT("\n");
    49,54c29
    <     CWindow * window;
    < 
    <     try
    <     {
    <         window = new CWindow
    <             ( 800, 600, TEXT("WINDOW"), &WindowProcedure, TEXT("TEST"), 
    ---
    >     CWindow window( 0, 0, 800, 600, TEXT("WINDOW"), &WindowProcedure, TEXT("TEST"), 
    57,61d31
    <     }
    <     catch( CError & e )
    <     {
    <         dout << e.errorString() << TEXT("\n");
    <         ::WSACleanup();
    63,66c33,34
    <         return 0;
    <     }
    < 
    <     window->show( SW_SHOW );
    ---
    >     window.centerScreen();
    >     window.show( SW_SHOW );
    83c51
    <         dout << ErrorMessage( TEXT("WinMain"), ret ) << TEXT("\n");
    ---
    >         dout << geterr("GetAddrInfo", ::WSAGetLastError()) << TEXT("\n");
    107c75
    <         dout << ErrorMessage( TEXT("WinMain"), ::WSAGetLastError() ) << TEXT("\n");
    ---
    >         dout << geterr("WSASocket", ::WSAGetLastError());
    135c103
    <         dout << ErrorMessage( TEXT("WinMain"), ::WSAGetLastError() ) << TEXT("\n");
    ---
    >         dout << geterr("bind", ::WSAGetLastError());
    143c111
    <     ret = ::WSAAsyncSelect( listener, window->getHwnd(), WM_LISTENING,
    ---
    >     ret = ::WSAAsyncSelect( listener, window.getHwnd(), WM_LISTENING,
    148c116
    <         dout << ErrorMessage( TEXT("WinMain"), ::WSAGetLastError() ) << TEXT("\n");
    ---
    >         dout << geterr("WSAAsyncSelect", ::WSAGetLastError());
    160c128
    <         dout << ErrorMessage( TEXT("WinMain"), ::WSAGetLastError() ) << TEXT("\n");
    ---
    >         dout << geterr("listen", ::WSAGetLastError());
    184a153,289
    > struct client
    > {
    >     client( SOCKET a, SOCKADDR b, HWND c ) 
    >         : s(a), sa(b), r(c), count(0)
    >     {
    >         dout << "client(SOCKET, SOCKADDR, HWND)" << "\n";
    > 
    >         UINT_PTR ret = ::SetTimer( r, ( UINT_PTR ) this, 1000, &tp );
    > 
    >         if( ret == 0 )
    >         {
    >             dout << geterr( "SetTimer", ::GetLastError() );
    >         }
    >         else
    >         {
    >             clean = true;
    >         }
    >     }
    > 
    >     client( SOCKET a, HWND b )
    >         : s(a), r(b), clean(false), count(0)
    >     {
    >         dout << "client(SOCKET, HWND)" << "\n";
    >     }
    > 
    >     client( const client & other )
    > 
    >         :
    > 
    >     s( other.s ),
    >     sa( other.sa ),
    >     r( other.r ),
    >     recv_buf( other.recv_buf ),
    >     count( other.count )
    > 
    >     {
    >         dout << "client(const client &)" << "\n";
    > 
    >         client & sss = const_cast< client & >( *this );
    >         client & ooo = const_cast< client & >( other );
    > 
    >         if( ooo.clean )
    >         {
    >             ::KillTimer( ooo.r, ( UINT_PTR ) &ooo );
    >             ooo.clean = false;
    >             ::SetTimer( r, ( UINT_PTR ) this, 1000, &tp );
    >             sss.clean = true;
    >         }
    >     }
    > 
    >     ~client( void )
    >     {
    >         dout << __FUNCTION__ << "\n";
    > 
    >         if( clean )
    >         {
    >             BOOL ret = ::KillTimer( r, ( UINT_PTR ) this );
    > 
    >             if( ret == 0 )
    >             {
    >                 dout << geterr( "KillTimer", ::GetLastError() );
    >             }
    >             else
    >             {
    >             }
    >         }
    >     }
    > 
    >     client & operator = ( const client & other )
    >     {
    >         dout << "client & operator = (const client &)" << "\n";
    > 
    >         client & sss = const_cast< client & >( *this );
    >         client & ooo = const_cast< client & >( other );
    > 
    >         s = other.s;
    >         sa = other.sa;
    >         r = other.r;
    >         recv_buf = other.recv_buf;
    >         count = other.count;
    > 
    >         if( ooo.clean )
    >         {
    >             ::KillTimer( ooo.r, ( UINT_PTR ) &ooo );
    >             ooo.clean = false;
    >             ::SetTimer( r, ( UINT_PTR ) this, 1000, &tp );
    >             sss.clean = true;
    >         }
    > 
    >         return *this;
    >     }
    > 
    >     static VOID CALLBACK tp
    >     (      
    >         HWND hwnd,
    >         UINT uMsg,
    >         UINT_PTR idEvent,
    >         DWORD dwTime
    >     )
    >     {
    >         dout << __FUNCTION__ << "\n";
    >         client * _this = ( client * ) idEvent;
    > 
    >         std::stringstream ss;
    >         ss << _this->count;
    >         dout << ss.str().c_str() << "\n";
    > 
    >         int ret = ::send( _this->s, ss.str().c_str(), 
    >             ss.str().length() + 1, 0 );
    > 
    >         if( ret == SOCKET_ERROR )
    >         {
    >             dout << geterr( "send", ::WSAGetLastError() );
    >         }
    > 
    >         _this->count++;
    >     }
    > 
    > 
    >     SOCKET s;
    >     SOCKADDR sa;
    >     HWND r;
    > 
    >     bool clean;
    >     int count;
    > 
    >     std::vector< char > recv_buf;
    > 
    >     bool operator == ( const client & other ) const
    >     {
    >         dout << __FUNCTION__ << "\n";
    >         return s == other.s;
    >     }  
    > 
    > };
    > 
    > 
    191a297
    >     static RECT s_rc = { 0 };
    193d298
    <     static std::vector< std::pair< SOCKET, SOCKADDR_IN > > users;
    195,196c300
    < 	switch (message)
    < 	{
    ---
    >     static std::vector< client > s_users;
    198c302,303
    < 	case WM_PAINT:
    ---
    > 	switch( message )
    > 	{
    200,201c305
    <         hdc = ::BeginPaint(window, &ps);
    <         ::EndPaint(window, &ps);
    ---
    >     case WM_CLOSE:
    203c307
    < 		break;
    ---
    >         dout << "WM_CLOSE\n";
    205c309,326
    < 	case WM_DESTROY:
    ---
    >         for( std::vector< client >::iterator i = s_users.begin();
    >             i != s_users.end(); ++i )
    >         {
    >             int ret = 0;
    >             ret = ::shutdown( i->s, SD_SEND );
    >             if( ret != SOCKET_ERROR )
    >             {
    >                 ret = ::closesocket( i->s );
    >                 if( ret == SOCKET_ERROR )
    >                 {
    >                     dout << geterr("closesocket", ::WSAGetLastError());
    >                 }
    >             }
    >             else
    >             {
    >                 dout << geterr("shutdown", ::WSAGetLastError());
    >             }
    >         }
    206a328
    >         s_users.clear();
    208d329
    < 		break;
    210c331
    <     case WM_LISTENING:
    ---
    >         break;
    212,213c333
    <         dout << TEXT("HERHEHREHREHRE\n");
    <         switch( WSAGETSELECTERROR( lParam ) )
    ---
    >     case WM_PAINT:
    214a335
    >             hdc = ::BeginPaint(window, &ps);
    216c337,341
    <         default:;
    ---
    >             std::basic_stringstream< TCHAR > s;
    >             s << s_users.size();
    > 
    >             ::TextOut( hdc, 0, 0, s.str().c_str(), s.str().length() );
    >             ::EndPaint(window, &ps);
    217a343
    >             break;
    219a346,347
    >     case WM_LISTENING:
    > 
    223,224c351,352
    <         case FD_READ:
    <         case FD_WRITE:
    ---
    >         case FD_READ: break;
    >         case FD_WRITE: break;
    229c357
    <                 SOCKADDR_IN accepted_data;
    ---
    >                 SOCKADDR accepted_data;
    233c361
    <                 accepted = ::WSAAccept( wParam, (SOCKADDR * ) &accepted_data, &accepted_data_size, 0, 0 );
    ---
    >                 accepted = ::accept( (SOCKET) wParam, &accepted_data, &accepted_data_size );
    236c364
    <                     dout << TEXT("ALERT!");
    ---
    >                     dout << geterr("WM_LISTENING - accept", ::WSAGetLastError());
    239c367
    <                 users.push_back( std::pair< SOCKET, SOCKADDR_IN >( accepted, accepted_data ) );
    ---
    >                 s_users.push_back( client( accepted, accepted_data, window ) );
    241c369
    <                 ::WSAAsyncSelect( users.back().first, window, 
    ---
    >                 ::WSAAsyncSelect( s_users.back().s, window, 
    243a372
    >                 ::InvalidateRect( window, 0, TRUE );
    247c376
    <         case FD_CLOSE:
    ---
    >         case FD_CLOSE: break;
    256,257c385
    <         dout << TEXT("HERHEHREHREHRE\n");
    <         switch( WSAGETSELECTERROR( lParam ) )
    ---
    >         switch( WSAGETSELECTEVENT( lParam ) )
    260c388,392
    <         default:;
    ---
    >         case FD_READ: 
    >             {
    >                 char buf[ 64 ];
    >                 int ret = ::recv( wParam, buf, sizeof( buf ), 0 );
    >                 std::vector< client >::iterator i;
    262c394,410
    <         }
    ---
    >                 if( ret != 0 )
    >                 {
    >                     if( ret == -1 )
    >                     {
    >                         dout << geterr("WM_CONNECTED_USERS - FD_READ", ::WSAGetLastError());
    >                     }
    >                     else
    >                     {
    >                         i = std::find( s_users.begin(), s_users.end(), client( wParam, window ) );
    > 
    >                         int j = 0; 
    > 
    >                         while( j < ret )
    >                         {
    >                             i->recv_buf.push_back( buf[j] );
    >                             j++;
    >                         }
    264,265c412,430
    <         switch( WSAGETSELECTEVENT( lParam ) )
    <         {
    ---
    >                         dout << "WM_CONNECTED_USERS - FD_READ - recv'd: " << &i->recv_buf[0] << "\n";
    >                     }
    >                 }
    > 
    >                 std::string s( i->recv_buf.begin(), i->recv_buf.end() );
    > 
    >                 if( s.substr( 0, 4 ) == "PING" )
    >                 {
    >                     dout << s << "\n";
    >                 }
    >             }
    >                 
    >             break;
    > 
    >         case FD_WRITE: 
    >             break;
    > 
    >         case FD_ACCEPT: 
    >             break;
    267,269d431
    <         case FD_READ:
    <         case FD_WRITE:
    <         case FD_ACCEPT:
    270a433
    >             {
    272,273c435
    <             ::shutdown( wParam, SD_SEND );
    <             ::closesocket( wParam );
    ---
    >                 dout << "WM_CONNECTED_USERS - FD_CLOSE\n";
    274a437,459
    >                 int ret = ::shutdown( wParam, SD_SEND );
    >                 if( ret != SOCKET_ERROR )
    >                 {
    >                     ret = ::closesocket( wParam );
    >                     if( ret == SOCKET_ERROR )
    >                     {
    >                         dout << geterr("closesocket",  ::WSAGetLastError());
    >                     }
    >                 }
    >                 else
    >                 {
    >                     dout << geterr("shutdown", ::WSAGetLastError());
    >                 }
    > 
    >                 std::vector< client >::iterator i =
    >                     std::find( s_users.begin(), s_users.end(), client( wParam, window ) );
    > 
    >                 s_users.erase( i );
    >                 ::InvalidateRect( window, 0, TRUE );
    > 
    >                 break;
    > 
    >             }
    282c467
    <         return ::DefWindowProc(window, message, wParam, lParam);
    ---
    >         return ::DefWindowProc( window, message, wParam, lParam );
    287a473
    >

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help with file reading/dynamic memory allocation
    By Quasar in forum C++ Programming
    Replies: 4
    Last Post: 05-17-2004, 03:36 PM
  2. problem with UDP WSAAsyncSelect socket, no callback message received???
    By hanhao in forum Networking/Device Communication
    Replies: 1
    Last Post: 03-29-2004, 11:59 AM
  3. Winsock Socket Model
    By Eibro in forum Networking/Device Communication
    Replies: 1
    Last Post: 07-11-2003, 01:07 PM
  4. socket newbie, losing a few chars from server to client
    By registering in forum Linux Programming
    Replies: 2
    Last Post: 06-07-2003, 11:48 AM
  5. WSAAsyncSelect I/O Mode :: Winsock
    By kuphryn in forum Windows Programming
    Replies: 1
    Last Post: 05-12-2002, 03:23 PM