Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Server-client(s) loop in C/C++ (Windows)

  1. Feb 23, 2007 #1
    Hi,
    I was wondering how to maintain constant communication (server send/client recv loop) using sockets in C/C++ (loop till client terminates connection). I can currently send/recv once bothways. But am unsure how to proceed to keep the communication going.

    I'm guessing an infinite loop would be involved but would this also require threads. I tried an infinite loop but they only sent once.

    Also for multiple clients is a server suppose to maintain all teh sockets in a list or tree?

    Thanks
    Neurocomp
     
  2. jcsd
  3. Feb 23, 2007 #2

    verty

    User Avatar
    Homework Helper

    I don't know but perhaps you could look at some networked source code.
     
  4. Feb 23, 2007 #3

    chroot

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    The socket will remain open until one side explicitly closes it or terminates. An infinite loop should be fine; perhaps the structure of your code is incorrect. If you'd like, you can show us a piece of your code and we can check it for correctness.

    - Warren
     
  5. Feb 24, 2007 #4
    yah the placement of the inner loops(for constant server-sending,client recving) was wrong...it 'd be nice if i actually looked at where i put the loops the first time i did it :rolleyes: It sends properly now till client termination.

    Now the question i have is how to maintain multiple clients...so that the server broadcasts the same updated info to each connected client?. So much easier using omp/mpi :rofl:

    Do i have to have a thread to listen for connectin clients(through the accept())?

    Thanks for the help in advance.
    neurocomp2003
     
  6. Feb 24, 2007 #5

    robphy

    User Avatar
    Science Advisor
    Homework Helper
    Gold Member

    I think you'll need to show some code in order to get specific suggestions.
     
  7. Feb 24, 2007 #6
    This is code i've been playign with from someone else's tutorial
    Code (Text):

    void Server(int port)
    {
      CSocket * tsocket;
      printf("\nServer=> Listening Socket-open on port: %d",port);
     
      // tutorial
      try
      {
        tsocket = new CSocket( port);
        printf("\nServer=> Hosting, Port %d open ",port);    
      }
      catch( CSocketException se)
      {  printf("\nClient=>Exception %s",se.Text()); return;
      }
    //*/
      printf("\nServer: Enter Server Mode [^C to abort]");
         
     while(1) //SERVER infinite loop
     {
       CSocket *clientSocket = tsocket->Accept();
       if( !clientSocket) continue;        

       while(1) // Inner loop server keep sending till clients disconntect
       {
          printf("\nServer: Sending String");          
          int bufsize = clientSocket->Write(strlen( SERVER_STR),SERVER_STR);
          printf("\nServer: %d bytes sent",bufsize);
          if(bufsize<0) break;
       }       
       delete clientSocket;
     }
     delete tsocket;
    }
     
    CSocket is a class that calls the winsock commands:
    WSAStartup(haven't called WSACleanup yet)
    socket; bind/listen; accept/connect; send/recv
    it also has two constructors: one for server(port) and client(ip2connect,port)
    -----------------------------------------------
    THe ideas that i'm trying to look at is that
    [1] on the server side the server would maintain a list of SOCKET or CSocket [2] in the inner loop the server would send to each SOCKET in the list.

    The trouble i have is understanding, is how the server keeps listening for connecting clients while it sends to clients in the list.

    Does this call for a thread?

    and solutions, suggestions or references would be of great help

    NC
     
  8. Feb 24, 2007 #7

    -Job-

    User Avatar
    Science Advisor

    Absolutely, you have to use threads otherwise while client A will have to wait while the server is servicing client B.
    Basically, sockets usually have a listen method. The listen method spins until a client establishes a connection, at which point it returns a socket (the details differ from language to language but the idea is the same). What you should do, when the listen method returns, is create a thread to service the client, so that the server can go back to listening.
    For example:
    Code (Text):
     while(1) //SERVER infinite loop
     {
       CSocket *clientSocket = tsocket->Accept();
       if( !clientSocket) continue;        
       //create thread to service socket here and forget about it
       //the thread will handle the client from here on
     }
     
    Last edited: Feb 24, 2007
  9. Feb 24, 2007 #8
    chroot/job thanks for the replies.

    Job: would it be sufficient to have 2 threads A &B where A acts as a listening thread and B acts to service all the clients? or do i have to have a thread for every client, ? I would think that the answer is no.
     
  10. Feb 24, 2007 #9

    -Job-

    User Avatar
    Science Advisor

    You should have one thread per client. I mean, you could have a single thread that services all clients, one by one using a Queue but that's not ideal, you'll have worse performance and probably end up with more code.
    Another problem with a single thread for servicing all clients is that if that thread terminates abruptly all client connections are dropped. Also, if one client needs more time to be serviced then every other client will have to wait. So definitely one thread per client.

    For the listener you can have it run under it's own thread as well or just under the main program. I usually have the listener in its own thread because it makes it easier to put an interface on it, should i need to.
     
  11. Feb 25, 2007 #10
    -Job- you are not correct on saying that not going for thread per client approach (having just a few threads or one thread) has worse performanse. A colleague of mine did just that (having just a few service threads) as part of his ph.d, he got up to 4x the troughtput compared to conventional thread-per-client approach, but he used some sofisticated native i/o functions he was explaining it to me but I wasnt that interested since.

    But thread-per-client is most simple and clean way of doing it. Code should be quite straight forward at least in Java(if it helps):

    Code (Text):
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;

    /**
       A server that listens to incoming connections
    */
    public class ProficioServer
    {  
       public static void main(String[] args) throws IOException
       {  
     
          final int SBAP_PORT = 8888;
          ServerSocket server = new ServerSocket(SBAP_PORT); // listen here for connection.
          System.out.println("Waiting for clients to connect...");
         
          while (true) // the infamous infinite loop
          {
             Socket s = server.accept(); // when new client will connect
             System.out.println("Client connected.");
             ProficioService service = new ProficioService (s); // we create new "service" this is just thread definition
             Thread t = new Thread(service); // wrap it in thread
             t.start(); // this will start a new thread with thread-per-client, note when this call will return sever will be able to process new client
          }
       }
    }
    for the thread definition

    Code (Text):
    import java.io.InputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.PrintWriter;
    import java.net.Socket;
    import java.util.Scanner;

    /**
       Print what the client has requested
    */
    public class ProficioService implements Runnable
    {
       /**
          Constructs a service object.
          @param aSocket the socket
       
       */
       public ProficioService(Socket aSocket)
       {
          s = aSocket;
       
       }

       public void run() // this is the method that will be called from the thread
       {
          try
          {
             try
             {
                in = new Scanner(s.getInputStream()); // input stream from the client
                out = new PrintWriter(s.getOutputStream()); // our output stream
                doService();   // method to do some stuff        
             }
             finally
             {
                s.close(); // it is important that we close socket when we are done
             }
          }
          catch (IOException exception)
          {
             exception.printStackTrace();
          }
       }

       /**
          Just prints what is on the input stream.
       */
       public void doService() throws IOException
       {      
         
             if (!in.hasNext()) return; // if by any chance input stream is empty just return
             String command = in.next();
         
            out.print(command); // just print what the request was
         
       }

       

       private Socket s;
       private Scanner in;
       private PrintWriter out;
     
    }
     
    This should be quite straightforward, in C++ must be a bit more painful to make such clean code.
     
    Last edited: Feb 25, 2007
  12. Feb 25, 2007 #11

    -Job-

    User Avatar
    Science Advisor

    Well, i think you and your friend are wrong. Think about webservers, for example, if a worker process enters into an infinite loop, which happens occasionaly, then the whole server is unavailable. Also a thread per client is much more scalable, you can expand the server's resources and be able to use them. Think about database connectivty as well, now you're using database servers in a sequential fashion. It must have been a specific scenario your friend focused on, so i wouldn't jump to conclusions and call me "incorrect" so quickly.
     
    Last edited: Feb 25, 2007
  13. Feb 25, 2007 #12
    job/haki: thanks for the input....

    as for thread per client being more scalable...you could always hav ea cut off limit to the # of clients per thread and spawn new threads once the limit has been reached...., but yay more things to worry about when coding....argh...this isn't gonna be fun for me...i dont' even get to touch the physics or math portion. Spent the first half of my RAship battling MFC....fun stuff.

    again, thank you for the help, its much appreciated, and learned quite a bit

    NC
     
  14. Feb 25, 2007 #13
    I think that thread per client is not scalable at all. Note: When your machine reaches N threads its CPU jumps to 100 % and then your machine is useless. Imagine having 10,000 clients connected, chances are you need not service 10,000 clients at the same time, 3,000 might be just connected and doing nothing now you don't want 3,000 Threads to waste precious processor time doing nothing do you? What my colleague did is he had M service threads that serviced only the clients that needed something done and didn't wasted processor power on thoes who were doing nothing. When in thread per client approach the server reached 100 % cpu usage with N clients connected in the new model (service threads) when the server had N clients connected its CPU usage was only 30 %.
     
  15. Feb 25, 2007 #14

    Hurkyl

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    If only there was some way to put those other 7,000 threads to sleep when inactive, so as not to waste processor cycles...
     
  16. Feb 25, 2007 #15

    -Job-

    User Avatar
    Science Advisor

    Like Hurkyl mentioned you can call Sleep(miliseconds) or an equivalent to have the OS keep a thread out of the CPU.

    Besides, if you have 10,000 threads, the OS still cycles through the threads allocating equal CPU time to every one, not just the first 3000, so the machine would never be "useless" like you said.

    Also, with your approach, if 1000 clients are connected, and the server is taking a while to process a client, then everyone waits. Meanwhile more and more clients queue up, and there will be very slow performance until the server eventually catches up, so as you can see it's not scalable at all.

    On the other hand with one thread per client, since the OS will schedule the threads with equal priority with some fair algorithm the threads are interleaved, this means that every client is serviced in a timely manner, and the only client that has to wait longer than usual is the one that is asking for alot of resources. This ensures clients don't queue up, or have at least a much higher queueing threshold.

    Finally, with one thread per client you can add multiple CPUs to the system and you'll be able to reap the rewards, unlike your single threaded strategy.
     
    Last edited: Feb 25, 2007
  17. Feb 26, 2007 #16

    Hurkyl

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    From the theoretical standpoint, both solutions (assuming a reasonable implementation) wind up behaving roughly the same:

    (1) data comes in
    (2) some glue code gets executed
    (3) the service routine is called on the data
    (4) some glue code gets executed.

    Similarly, there will be similar data structures in memory -- either solution needs to keep a data structure that holds the state of the client's session.


    IMO, the primary advantage of the one-thread-per-client approach is that it takes advantage of the available, robust multi-threading features. (e.g. a java Thread, or a C/C++ pthread on a POSIX system, or something else entirely)

    If you don't use those features, you still have to reinvent much of the same functionality. A win may be possible, but the only gain you can possibly get is to eliminate some of the overhead of the general-purpose threading solution.
     
  18. Feb 26, 2007 #17

    -Job-

    User Avatar
    Science Advisor

    I'm not in agreement there because that's unrealistic. I think the mistake is in assuming that all clients are the same. Clients have different connection speeds and different service needs.

    I think we can make use of the traffic analogy. More lanes, less traffic jams.
    Single lane, single point of failure.

    Besides, we should also take into consideration that the service thread gets swapped naturally out by the OS. At any given time there are many other threads competing for the CPU. If you have more threads chances are you'll have more CPU time.
     
  19. Feb 26, 2007 #18
    what is "glue code".
     
  20. Feb 26, 2007 #19
    though this is http server, it is quite small for code to be actually read, and it is embeddable in your own program.
     
  21. Aug 13, 2007 #20
    This is a very good discussion. Learnt quite a bit from it. I have a question in this context. The socket server has this infinite while loop for server to keep listening. The problem I am having is that the process which launches the server is held up. In other words the process which has other functionalities cannot be accessed because server is holding up the process (with or without the loop for listen). I tried multithreading but then I run into memory access violation issues. Please advise !!
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook

Have something to add?



Similar Discussions: Server-client(s) loop in C/C++ (Windows)
  1. C# Window Resizing (Replies: 5)

Loading...