CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 3 of 3
  1. #1
    Join Date
    Dec 2008
    Posts
    56

    select() on a socket

    I am having an issue with an overzealous select() call. I works as expected until I send a single UDP message to my socket. Then it reports that there is activity even after the application performs a read on the socket.

    Is there any special way to "clear" the internal state of the socket so that it select() understands that the socket has been serviced?

    Here's the snippet of code that I am using for the select():
    Code:
    UINT CUdpComm::MonitorReadEvent()
    {
       fd_set savefds;
       FD_ZERO(&savefds);
       FD_SET(m_server->GetHandle(), &savefds);    // GetHandle() returns a SOCKET
    
       while (m_server->Connected())
       {
          struct timeval timeout = {1, 0};
          fd_set readfds = savefds;
          int sel = ::select(m_server->GetHandle(), &readfds, 0, 0, &timeout);
    
          if (sel == 0) continue;   // timeout
    
          if (sel > 0 && FD_ISSET(m_server->GetHandle(), &readfds))
          {
             ::PostMessage(m_wnd, WM_USER_COMMPORT, 0, 0);
          }
    
          if (sel == SOCKET_ERROR)  AfxMessageBox("Error with select().");
       }
    
       return 0;
    }
    Above, the m_server is a CUdpSocket object. Here's how it is receiving data, when the callback routine that is associated with WM_USER_COMMPORT is called:
    Code:
    int CUdpSocket::Receive(BYTE buf[], short bufSize, CString& fromAddress, int& fromPort)
    {
       sockaddr_in addr;
       socklen_t addrLen = sizeof(addr);
    
       int rtn = recvfrom(m_socket, (char*) buf, bufSize, 0, (sockaddr*) &addr, (socklen_t*) &addrlen);
    
       if (rtn >= 0)
       {
          fromAddress = inet_ntoa(addr.sin_addr);
          fromPort = ntohs(addr.sin_port);
       }
    
       return rtn;
    }
    I've verified that the UDP message is indeed being received (obviously in its entirety... it is only 6 bytes long), however I cannot explain why the select() is telling me again and again that there is activity on the socket... even after a read is performed, and no more messages are being sent by the client. This hoses my application up because when it attempts the recvfrom(), it blocks... and then my app is deadlocked.

    Any ideas what M$ VC++ expects of my application? Under Linux, the underlying principles shown above would work.

  2. #2
    Join Date
    Feb 2005
    Posts
    2,160

    Re: select() on a socket

    I think I've read before that the M$ stack does some funny stuff with the fd_set structure and that you should always assume it to be undefined after the select call returns. I looked at some working code and I've got my FD_SET and FD_ZERO macros included in the while loop so as to reset the fd_set struct at every iteration of the loop.

  3. #3
    Join Date
    Dec 2008
    Posts
    56

    Re: select() on a socket

    hoxsiew, you are correct; the fd_set (and the timeout period, if used) needs to be (re)set before each call to the select().

    I found the problem to the issue I was having. The code, which I inherited, is a multi-threaded application; in one thread, the select() is being performed. In another thread, the recvfrom() is performed. When debugging the application within the thread where the select() was performed, I found that the other thread was never executed, thus select() was constantly reminding me that there is data to be read from the socket.

    Personally, if I had to design a multi-threaded application that employs a socket, I would never separate the select() from the recvfrom().

    My "band-aid" solution to the problem was to configure the socket to be non-blocking, thus ensuring that it would not block when performing a recvfrom() when no data is present.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured