Thread: Help in experience gaining for network programming

  1. #1
    Registered User
    Join Date
    Oct 2004
    Posts
    100

    Help in experience gaining for network programming

    Hi all,

    I believe a firm understanding of network programming is something every programmer should have in his armory. Although I know how to use the basics of socket programming to communicate between a client and a server I do not have experience of network programming "best practices".

    To help me learn this I intend to write a client and server application like a messaing program, purely to help me learn how to use winsock correctly. The server will be ran on my PC and allow multiple buddies to connect to it and chat, share files, play games etc etc. To make it simple the multiple client buddies cant talk to each other but only to the single server buddy. The server buddy must be able to chat to multiple buddies at any time and show when each buddy is typing a message. It should also be able to read the status of buddies and acknowledge any changes to their screen name.

    Now with my current winsock knowledge I can write the above program already but like most programming designs there is the right way to do it and there are many wrong ways to do it. It is the learning of the right way to do it that I plan to learn with this project.

    So my question is to you is (without requring code examples just "best practices"):

    How would you design such a system to make it stable, flexible and easily maintainable? Should the socket be wrapped in a RAII class and im assuming it should all be multithreaded for each buddy connection? If so how stable is winsock in a multithreaded environment?
    Also how would you design the communication between the server and client so they communicate effectively in the face of errors, lost packets etc.

    I know im asking quite a lot but I consider this knowledge to be invaluable.

    Thanks for any help

  2. #2
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Winsock provides the (roughly) same API as POSIX sockets, so it's not really winsock you need to learn, but the basic ideas underlying network programming in general. If you're already using UNIX sockets, you should be able to convert to winsock with few problems.

    At the heart of any network communications program is a main loop that looks like this:

    Code:
    while(TRUE)
    {
        wait_for_io_activity();
        read_incoming_messages();
        process_incoming_messages();
        send_outgoing_messages();
    }
    The details of the loop are obviously left out. For a one thread per client system, this loop will be very simple. For a program that handles multiple clients per thread, this loop is much more complicated, with message serialization/deserialization, queuing, and background ticking.

    If your application generates events from timers (in other words, it does something more than just respond to client input), the wait_for_io_activity() function is where timeouts are handled.

    The general idea is that you have queues of incoming and outgoing messages, and these are serialized/deserialized from the data between client and server. If you want to avoid blocking, this introduces a layer of buffering which makes things harder. Thus the trend recently to handle only a single client per each thread.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  3. #3
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by cloudy View Post
    im assuming it should all be multithreaded for each buddy connection?
    It is possible to avoid this by using NON_BLOCK on the server socket and then checking multiple file descriptors in the single loop mentioned by brewbuck. The only issue I encountered with this is that if you use read()/recv() on a non-blocking socket in an infinite loop, the process will max the processor out when there is nothing to recieve. Including a very short time delay (1/1000th sec) between calls prevents this (it could be longer -- as long as it's there -- since NON-BLOCK does not mean you have to "catch" the data on time).

    You can also use select() to do this, but I'm not sure if you can use select() with winsock. Anyway, it will much simplify things while you get all the networking details worked out.

    Or if you are that comfortable with threading, you could just start writing it that way from scratch.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  4. #4
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Quote Originally Posted by MK27 View Post
    You can also use select() to do this, but I'm not sure if you can use select() with winsock. .
    Yes you can
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  5. #5
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by MK27 View Post
    It is possible to avoid this by using NON_BLOCK on the server socket and then checking multiple file descriptors in the single loop mentioned by brewbuck. The only issue I encountered with this is that if you use read()/recv() on a non-blocking socket in an infinite loop, the process will max the processor out when there is nothing to recieve. Including a very short time delay (1/1000th sec) between calls prevents this (it could be longer -- as long as it's there -- since NON-BLOCK does not mean you have to "catch" the data on time).
    Non blocking reads are not something you would normally use. If more than one client is being handled by a single thread, this should be done with select(). The complexity arises when your server needs to do something else while also waiting for client interaction.

    My preferred method for handling client IO and timeout events is to maintain a heap (the data structure, not the memory allocator) of timer events, with the soonest-firing event on the top of the heap. Before calling select(), you remove the heap root, check its timeout, and use that value for your call to select(). If select() times out, you know the timer has expired and you can go off and handle it. If select() doesn't time out, you must compute the time remaining until the event fires, then reinsert it into the heap.

    This "asynchronous core" is common to most network programs, and it's something you should write once, get it working, and leverage that in future projects.

    As far as handling each client in a single thread, this is popular these days, but it has some serious downsides. For one, now you are writing multithreaded code, and you need to deal with synchronization properly. For another, how are you going to handle 100 clients? Are you really going to start 100 threads?
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Programming opportunities! (Midway Games, Inc)
    By Midwayrecruiter in forum Projects and Job Recruitment
    Replies: 0
    Last Post: 08-20-2008, 11:02 AM
  2. Are You An Experienced Programmer? Do You Like Football/soccer? (uk)
    By Mark Smulders in forum Projects and Job Recruitment
    Replies: 2
    Last Post: 06-28-2007, 01:53 AM
  3. Printing in XP using C
    By j2005 in forum C Programming
    Replies: 16
    Last Post: 03-07-2006, 06:34 AM
  4. 32-bit ASM or COM :: Experience
    By kuphryn in forum Windows Programming
    Replies: 3
    Last Post: 10-04-2002, 12:39 PM
  5. Gaining Experience in C/C++ Programming
    By stevey in forum A Brief History of Cprogramming.com
    Replies: 19
    Last Post: 03-29-2002, 12:45 PM