Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. O.O All my knowledge about asynchronous sockets and message pumps broken.. help..

O.O All my knowledge about asynchronous sockets and message pumps broken.. help..

Scheduled Pinned Locked Moved C / C++ / MFC
helpc++sysadminlearning
5 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Offline
    K Offline
    Kuniva
    wrote on last edited by
    #1

    Ok, i have a very serious problem (allthough it is probably just due to something rediculous i overlooked like these problems usually are). I have been programming with winsock and windows for a few years now so i like to think i know what i'm doing. During these years i have always kind of avoided MFC, so now i thought, why not make it easy on myself and use MFC. This is the situation, and i will try to sketch it as clearly as possible: I have an MFC dialog based application, one main dialog window based on the CDialog class and then i have a socket class based on CSocket in which i override the OnClose(), OnConnect(), OnReceive() and OnSend() methods which all call a function in my main Dialog class (using a parent pointer which i set in OnInitDialog() of my main dialog). Now.. the application needs to connect to a server when a button is pressed or whatever, but because i want to be able to tell when a connection fails (either refused or timed out) i keep the socket in blocking mode (which is the default for CSockets anyway) and try to connect. Then when the Connect() method succeeds (returns TRUE) then i use AsyncSelect() on the socket to register to right notifications (FD_CLOSE, FD_CONNECT, FD_READ and FD_WRITE). So of course OnConnect() will never be called, thats obvious, because the connection was established when the socket was still in blocking mode. But the OnReceive() event should work, and it does. Only the ABNORMALLY WEIRD (to me anyway) thing is.. well after the connection succeeded i send a string to the server, and the server replies with two strings (each command is terminated by '\n') which i parse in OnReceive() like this:

    char pText\[4096\];
    CString strTemp;
        //MessageBox("msg1"); MESSAGE 1
    int nResult = m\_hSocket.Receive(pText, sizeof(pText));
    //MessageBox("test"); MESSAGE 2
    if (SOCKET\_ERROR == nResult)
    {
    	MessageBox("An error occured while receiving data...",NULL,MB\_ICONERROR);	
    }
    else
    {
    
    	pText\[nResult\] = NULL;
    
    	strTemp = CString(pText);
    	//MessageBox((LPCTSTR)strTemp);
    
    	for(int i=0;i
    

    Where szLineBuffer is just a global variable to my class which is used to store text when a command did not fit into one received chunk. Now notice where i put MESSAGE 1 and MESSAGE 2. This is the odd part, when i uncomment MESSAGE 1 to display a messagebo

    K M 2 Replies Last reply
    0
    • K Kuniva

      Ok, i have a very serious problem (allthough it is probably just due to something rediculous i overlooked like these problems usually are). I have been programming with winsock and windows for a few years now so i like to think i know what i'm doing. During these years i have always kind of avoided MFC, so now i thought, why not make it easy on myself and use MFC. This is the situation, and i will try to sketch it as clearly as possible: I have an MFC dialog based application, one main dialog window based on the CDialog class and then i have a socket class based on CSocket in which i override the OnClose(), OnConnect(), OnReceive() and OnSend() methods which all call a function in my main Dialog class (using a parent pointer which i set in OnInitDialog() of my main dialog). Now.. the application needs to connect to a server when a button is pressed or whatever, but because i want to be able to tell when a connection fails (either refused or timed out) i keep the socket in blocking mode (which is the default for CSockets anyway) and try to connect. Then when the Connect() method succeeds (returns TRUE) then i use AsyncSelect() on the socket to register to right notifications (FD_CLOSE, FD_CONNECT, FD_READ and FD_WRITE). So of course OnConnect() will never be called, thats obvious, because the connection was established when the socket was still in blocking mode. But the OnReceive() event should work, and it does. Only the ABNORMALLY WEIRD (to me anyway) thing is.. well after the connection succeeded i send a string to the server, and the server replies with two strings (each command is terminated by '\n') which i parse in OnReceive() like this:

      char pText\[4096\];
      CString strTemp;
          //MessageBox("msg1"); MESSAGE 1
      int nResult = m\_hSocket.Receive(pText, sizeof(pText));
      //MessageBox("test"); MESSAGE 2
      if (SOCKET\_ERROR == nResult)
      {
      	MessageBox("An error occured while receiving data...",NULL,MB\_ICONERROR);	
      }
      else
      {
      
      	pText\[nResult\] = NULL;
      
      	strTemp = CString(pText);
      	//MessageBox((LPCTSTR)strTemp);
      
      	for(int i=0;i
      

      Where szLineBuffer is just a global variable to my class which is used to store text when a command did not fit into one received chunk. Now notice where i put MESSAGE 1 and MESSAGE 2. This is the odd part, when i uncomment MESSAGE 1 to display a messagebo

      K Offline
      K Offline
      Kuniva
      wrote on last edited by
      #2

      BTW, even if the Receive() method on the socket somehow lets the CSocket class know that the reveive has been handled and that it can now handle other events, i still dont see how my scenario can happen since the code of the CSocket class should still be frozen when it calls the OnReceive method of my dialog. Kuniva --------------------------------------------

      1 Reply Last reply
      0
      • K Kuniva

        Ok, i have a very serious problem (allthough it is probably just due to something rediculous i overlooked like these problems usually are). I have been programming with winsock and windows for a few years now so i like to think i know what i'm doing. During these years i have always kind of avoided MFC, so now i thought, why not make it easy on myself and use MFC. This is the situation, and i will try to sketch it as clearly as possible: I have an MFC dialog based application, one main dialog window based on the CDialog class and then i have a socket class based on CSocket in which i override the OnClose(), OnConnect(), OnReceive() and OnSend() methods which all call a function in my main Dialog class (using a parent pointer which i set in OnInitDialog() of my main dialog). Now.. the application needs to connect to a server when a button is pressed or whatever, but because i want to be able to tell when a connection fails (either refused or timed out) i keep the socket in blocking mode (which is the default for CSockets anyway) and try to connect. Then when the Connect() method succeeds (returns TRUE) then i use AsyncSelect() on the socket to register to right notifications (FD_CLOSE, FD_CONNECT, FD_READ and FD_WRITE). So of course OnConnect() will never be called, thats obvious, because the connection was established when the socket was still in blocking mode. But the OnReceive() event should work, and it does. Only the ABNORMALLY WEIRD (to me anyway) thing is.. well after the connection succeeded i send a string to the server, and the server replies with two strings (each command is terminated by '\n') which i parse in OnReceive() like this:

        char pText\[4096\];
        CString strTemp;
            //MessageBox("msg1"); MESSAGE 1
        int nResult = m\_hSocket.Receive(pText, sizeof(pText));
        //MessageBox("test"); MESSAGE 2
        if (SOCKET\_ERROR == nResult)
        {
        	MessageBox("An error occured while receiving data...",NULL,MB\_ICONERROR);	
        }
        else
        {
        
        	pText\[nResult\] = NULL;
        
        	strTemp = CString(pText);
        	//MessageBox((LPCTSTR)strTemp);
        
        	for(int i=0;i
        

        Where szLineBuffer is just a global variable to my class which is used to store text when a command did not fit into one received chunk. Now notice where i put MESSAGE 1 and MESSAGE 2. This is the odd part, when i uncomment MESSAGE 1 to display a messagebo

        M Offline
        M Offline
        Mike Dimmick
        wrote on last edited by
        #3

        Your underlying problem is that the MessageBox API call has a message pump within it. If you already know how to use WinSock, stick to that. The CSocket and CAsyncSocket classes are generally considered to be broken. You may find the Winsock Programmer's FAQ[^] helpful. Do your comms on a separate thread and post notification messages back to the UI thread using PostMessage. If you want the comms thread to block waiting for a response from the UI, try SendMessageTimeout instead. Stability. What an interesting concept. -- Chris Maunder

        K 1 Reply Last reply
        0
        • M Mike Dimmick

          Your underlying problem is that the MessageBox API call has a message pump within it. If you already know how to use WinSock, stick to that. The CSocket and CAsyncSocket classes are generally considered to be broken. You may find the Winsock Programmer's FAQ[^] helpful. Do your comms on a separate thread and post notification messages back to the UI thread using PostMessage. If you want the comms thread to block waiting for a response from the UI, try SendMessageTimeout instead. Stability. What an interesting concept. -- Chris Maunder

          K Offline
          K Offline
          Kuniva
          wrote on last edited by
          #4

          Uhm, thank you for this explanation, i had read before that the Socket classes from MFC were considered to be a bit faulty, but never knew they were considered broken.. hmm. And i have read the Winsock Programmer's FAQ already more than once ;). I know my way around the Winsock API, just not MFC.. What is very interesting is this message pump of the MessageBox, i'm afraid i don't quite understand.. I mean, if the messagebox is a modal dialog and it has it's own message pump, what difference does it make? As long as the messagebox is displayed the message pump of the main dialog is still frozen and cannot process messages isn't it? If you could explain, because it is still bugging me... Another thing i would like to mention for everyone who ever ran into the same program is this: I was able to fix my problem by Switching the socket into blocking mode at the start of my OnReceive method like this:

          DWORD dw = (DWORD)0;
          
          m\_hSocket.AsyncSelect(0);
          m\_hSocket.IOCtl(FIONBIO,&dw);
          

          And switching it back to asynchronous mode like this:

          if(m\_hSocket!=INVALID\_SOCKET)
          	m\_hSocket.AsyncSelect(FD\_CLOSE | FD\_CONNECT | FD\_READ | FD\_WRITE);
          

          The condition is just there because if certain data is received i might call Close() on the socket and if u try AsyncSelect() after a Close() u get an assertion failure. Thank you very much for your reply. Kuniva --------------------------------------------

          M 1 Reply Last reply
          0
          • K Kuniva

            Uhm, thank you for this explanation, i had read before that the Socket classes from MFC were considered to be a bit faulty, but never knew they were considered broken.. hmm. And i have read the Winsock Programmer's FAQ already more than once ;). I know my way around the Winsock API, just not MFC.. What is very interesting is this message pump of the MessageBox, i'm afraid i don't quite understand.. I mean, if the messagebox is a modal dialog and it has it's own message pump, what difference does it make? As long as the messagebox is displayed the message pump of the main dialog is still frozen and cannot process messages isn't it? If you could explain, because it is still bugging me... Another thing i would like to mention for everyone who ever ran into the same program is this: I was able to fix my problem by Switching the socket into blocking mode at the start of my OnReceive method like this:

            DWORD dw = (DWORD)0;
            
            m\_hSocket.AsyncSelect(0);
            m\_hSocket.IOCtl(FIONBIO,&dw);
            

            And switching it back to asynchronous mode like this:

            if(m\_hSocket!=INVALID\_SOCKET)
            	m\_hSocket.AsyncSelect(FD\_CLOSE | FD\_CONNECT | FD\_READ | FD\_WRITE);
            

            The condition is just there because if certain data is received i might call Close() on the socket and if u try AsyncSelect() after a Close() u get an assertion failure. Thank you very much for your reply. Kuniva --------------------------------------------

            M Offline
            M Offline
            Mike Dimmick
            wrote on last edited by
            #5

            Because the message box runs a message loop, your code can go re-entrant if another thread posts or sends messages to your window, or if a timer fires. I think that's what you were seeing. Part of the issue is that sent messages are always processed within the GetMessage call of the message loop. The other part is that the message loop inside MessageBox appears to pump messages for all windows, not just the message box window itself. Stability. What an interesting concept. -- Chris Maunder

            1 Reply Last reply
            0
            Reply
            • Reply as topic
            Log in to reply
            • Oldest to Newest
            • Newest to Oldest
            • Most Votes


            • Login

            • Don't have an account? Register

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • World
            • Users
            • Groups