Thread: Single-threaded Winsock

  1. #1
    Registered /usr
    Join Date
    Aug 2001
    Location
    Newport, South Wales, UK
    Posts
    1,273

    Single-threaded Winsock

    Hello,

    Is a WM_TIMER the only way to operate a Winsock connection and a window in a single thread? I like to practise working under restrictions (Asynchronous Winsock isn't permitted)

  2. #2
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    I made a Socket class that has a "hasData()" function that uses select(). That way a server can loop through the client Socket's, only receiving if there's data to be had, and doesn't get tied up with any one client.

    **Note: select() will let you know if a listening socket has clients waiting to connect, so you don't have to block for the accept()'s either.
    Just Google It. √

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

  3. #3
    Registered /usr
    Join Date
    Aug 2001
    Location
    Newport, South Wales, UK
    Posts
    1,273
    Yeah, but I mean, in order to get it working properly in a single thread and keep a window's message loop going I'd have to use select(...) via a WM_TIMER of a short duration?

  4. #4
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Not necessarily. This is my code:
    Code:
    bool hasData(SOCKET sock)
    {
    	timeval t = {0,0};
    	fd_set fds;
    	FD_ZERO(&fds);
    	FD_SET(sock, &fds);
    
    	return (::select(0, &fds, NULL, NULL, &t) > 0);
    }
    Then, if sock is a listening socket, hasData() will return true if there is a client waiting to connect, or if it's a normal socket that sends/receives data, it will return true if data is waiting to be received.

    Initializeing the timeval to {0,0} means that if there are no sockets with incoming connections/data, select() will return immediately, instead of waiting for a socket to have data.

    This is probably not the best way of doing things, but it works and is pretty convenient a lot of the time.
    Just Google It. √

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

  5. #5
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    The first argument of select() specifies the highest number of a socket descriptor that will be examined plus one
    I don't know about that... Maybe this is only a Windows thing, as you said, but straight from MSDN:
    int select (
    int nfds,
    fd_set FAR * readfds,
    fd_set FAR * writefds,
    fd_set FAR * exceptfds,
    const struct timeval FAR * timeout
    );

    Parameters
    nfds
    [in] This parameter is ignored; it is included only for
    compatibility with Berkeley sockets.
    Just Google It. √

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

  6. #6
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Well, portability is out of the question for me anyways since I'm doing a Windows app, but I guess it would be good to learn the berkeleian way anyways, just in case I ever change an OS...
    Just Google It. √

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

  7. #7
    Registered /usr
    Join Date
    Aug 2001
    Location
    Newport, South Wales, UK
    Posts
    1,273
    I think I need to put my question into context before I can get any useful answers...

    I have a "download window", which has a static text control displaying information about the download and a progress bar showing how much has been downloaded. I must, in essence, simulataneously (Or as near as can be gotten) check for data to be received on an open socket as well as update the window. The window must also be able to deal with user events without being held up in any way, in a single thread.

    Now, what you've told me is a method of checking whether a socket has any events waiting on it. What I was asking was how you could tie that in with allowing normal paint events, etc. to occur without any blockages. As far as I can see, I would:-

    1. Start a WM_TIMER with a short duration (0.1 seconds or something), in the WM_CREATE event of the window.

    2. In the WM_TIMER event, call select(...) on the socket to see if anything's there. If there is, get it and update the progress bar.

    That way, the download would be handled in a fashion similar to any other event, which I think would not be good for performance. The only other way I could think of doing it would be to call select(...) inside the message loop (The GetMessage(...) - DispatchMessage(...) one), although any delay in the use of recv would hold up the loop completely, which is also not good.

  8. #8
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Code:
    MSG msg;
    while(!done)
    {
         while(PeekMessage(...))
         {
              (...)
         }
         if(hasData(theSocket))
         {
              recv(theSocket, ...);
              updateProgressBar();
         }
    }
    any delay in the use of recv would hold up the loop completely, which is also not good.
    There would BE no delay with recv(), since recv() doesn't get called unless there's already data to be received.
    Just Google It. √

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

  9. #9
    I lurk
    Join Date
    Aug 2002
    Posts
    1,361
    I would suggest against using using select(..) on Windows. There are plenty of faster, and better alternatives. Check out OVERLAPPED completion routines or completion ports if you're looking for high performance/scalability.

  10. #10
    I lurk
    Join Date
    Aug 2002
    Posts
    1,361

    Re: Single-threaded Winsock

    Originally posted by SMurf
    Hello,

    Is a WM_TIMER the only way to operate a Winsock connection and a window in a single thread? I like to practise working under restrictions (Asynchronous Winsock isn't permitted)
    This is pointless. Why can't you use asyncronous sockets? Using a timer is inefficient. If you set it to a short interval, you're eating CPU time. Plus, the timer interval creates a minimum time which clients must wait to be serviced.

  11. #11
    Registered /usr
    Join Date
    Aug 2001
    Location
    Newport, South Wales, UK
    Posts
    1,273
    Ah, riiiiiiiight, I see. I kept thinking that what I was trying to do would cause some sort of blockage because IE gets regularly reduced to a window full of white while its status bar says "Done" when I load a page.

    Perhaps it's a Microsoft quirk.

    And I like to write code that's broadly compatible with other platforms, Ayebro. You can't get WSAAsync... anywhere else.
    Last edited by SMurf; 07-02-2003 at 04:17 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Winsock issues
    By tjpanda in forum Windows Programming
    Replies: 3
    Last Post: 12-04-2008, 08:32 AM
  2. Single Entry Single Exit
    By robwhit in forum C Programming
    Replies: 5
    Last Post: 11-11-2007, 01:34 PM
  3. Winsock Messaging Program
    By Morgul in forum Windows Programming
    Replies: 13
    Last Post: 04-25-2005, 04:00 PM
  4. Where do I initialize Winsock and catch messages for it?
    By Lithorien in forum Windows Programming
    Replies: 10
    Last Post: 12-30-2004, 12:11 PM
  5. fancy strcpy
    By heat511 in forum C++ Programming
    Replies: 34
    Last Post: 05-01-2002, 04:29 PM