Thread: Best way to poll sockets?

  1. #1
    Registered User
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    217

    Best way to poll sockets?

    I'm making a server emulator for an old mmo and would like to know the best way to poll sockets. At the moment i've got a class called SoxPoller that uses select. The code below is the class:
    Code:
        SoxPoller::SoxPoller()
        {
            FD_ZERO(&readSet);
            FD_ZERO(&writeSet);
            FD_ZERO(&errorSet);
            range = 0;
            options = 0;
        }
    
        void SoxPoller::AddSocket(const Socket& s, int options)
        {
            unsigned int socketId = s.GetSocket();
            this->options |= options;
    
            if(options & POLL_READ)
                FD_SET(socketId, &readSet);
    
            if(options & POLL_WRITE)
                FD_SET(socketId, &writeSet);
    
            if(options & POLL_ERROR)
                FD_SET(socketId, &errorSet);
    
            if(socketId > range)
                range = socketId;
        }
    
        bool SoxPoller::IsSet(const Socket& s, int option)
        {
            unsigned int socketId = s.GetSocket();
            if(option == POLL_READ)
                return FD_ISSET(socketId, &readSet);
    
            if(option == POLL_WRITE)
                return FD_ISSET(socketId, &writeSet);
    
            if(option == POLL_ERROR)
                return FD_ISSET(socketId, &errorSet);
    
            return false;
        }
    
        int SoxPoller::Poll(int timeOut)
        {
            struct timeval timev;
            timev.tv_sec = 0;
            timev.tv_usec = timeOut;
    
            return select(range + 1, &readSet, &writeSet, &errorSet, (timeOut >= 0 ? &timev : NULL));
        }
    But i've read select can only do like 64 sockets at a time. Linux has a method called "poll" but it's not available on windows. I know windows has "async" sockets that uses events but i want the server to be cross platform. What's the best way i can poll these sockets?

  2. #2
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    I doubt you'll find an effective method that works on both platforms. You'll also have the same limitation with any method that uses Events, since WaitForMultipleObjects() etc. has an upper limit of 63 or 64 handles. On the Windows side of things, you could try asynchronous sockets using the message queue (that seems to be how most people use them), or Overlapped completion routines, or else IOCP (IO completion ports).

    I've heard that IOCP is the most scalable/efficient for large-scale servers (I don't have any benchmarks or proof), but in general you may find IOCP and completion routines to be harder to write code for, since they notify you when an operation is *done*, as opposed to when an operation is *ready*. On the flip side, they don't require a message queue, making them more flexible from the standpoint of multithreading.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  3. #3
    Registered User
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    217
    I've decided all i'm going to do is add this warning at runtime:

    Code:
            if(FD_SETSIZE < maxPlayers)
            {
                log << LogHeader() << "WARNING: FD_SETSIZE " << FD_SETSIZE << " is smaller than the maximum players. "
                    "The maximum players has been changed to " << FD_SETSIZE << ". If you want more players, you need to "
                    "recompile the server with a larger FD_SETSIZE value.\n";
                maxPlayers = FD_SETSIZE;
            }
    Last edited by 39ster; 07-19-2008 at 11:22 PM.

  4. #4
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    There are two primary methods for handlign multiple socket connections. Thread per client, or polling. Polling is by far the fastest, although most difficult to impliment. Rather than use WaitForMultipleObjects, use WaitForSingleObject() with a timeout of zero. The return value will tell you whether it returned due to timeout, or from being signlaled. You can then queue that socket for service by your worker threads.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. multiple UDP sockets with select()
    By nkhambal in forum Networking/Device Communication
    Replies: 2
    Last Post: 01-17-2006, 07:36 PM
  2. Raw Sockets and SP2...
    By Devil Panther in forum Networking/Device Communication
    Replies: 11
    Last Post: 08-12-2005, 04:52 AM
  3. Starting window sockets
    By _Cl0wn_ in forum Windows Programming
    Replies: 2
    Last Post: 01-20-2003, 11:49 AM
  4. Today on Cprogramming....When Polls go bad?
    By incognito in forum A Brief History of Cprogramming.com
    Replies: 10
    Last Post: 01-25-2002, 01:41 PM
  5. Poll this Poll that
    By ski6ski in forum A Brief History of Cprogramming.com
    Replies: 6
    Last Post: 09-28-2001, 04:19 AM