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

  • C/C++
  • Thread starter neurocomp2003
  • Start date
  • Tags
    Loop Windows
In summary: but you'll have to keep track of the number of clients so it doesn't exceed the number of threads you have.
  • #1
neurocomp2003
1,366
3
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
 
Technology news on Phys.org
  • #2
I don't know but perhaps you could look at some networked source code.
 
  • #3
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
 
  • #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
 
  • #5
I think you'll need to show some code in order to get specific suggestions.
 
  • #6
This is code I've been playign with from someone else's tutorial
Code:
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
 
  • #7
neurocomp2003 said:
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

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:
 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:
  • #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.
 
  • #9
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.
 
  • #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:
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:
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:
  • #11
haki said:
-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.

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:
  • #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 going to 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
 
  • #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 %.
 
  • #14
haki said:
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?
If only there was some way to put those other 7,000 threads to sleep when inactive, so as not to waste processor cycles...
 
  • #15
haki said:
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?

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 a lot 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:
  • #16
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.
 
  • #17
Hurkyl said:
From the theoretical standpoint, both solutions (assuming a reasonable implementation) wind up behaving roughly the same:

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.
 
  • #18
what is "glue code".
 
  • #19
though this is http server, it is quite small for code to be actually read, and it is embeddable in your own program.
 
  • #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 !
 
  • #21
The call to accept() is a blocking call. You might be able to accomplish the same functionality with select(), but it's not worth it. Learn how to use threads properly.

- Warren
 
  • #22
-Job- said:
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.

Even though this is an ancient thread, I feel compelled to mention that haki is right, and you are wrong. What haki is describing is a thread pool; too bad he did not explicitly label the concept.

Thread pools are almost always a better implementation than one-thread-per-client. The start up and shut down costs of creating a new thread can be significant, so it makes sense to re-use the same threads over and over again. Futhermore, hard drive access, caches, and other low-level functions perform better with greater locality. You don't want 3,000 threads trying to read 3,000 places on the disk "simultaneously." You want to reduce the number of threads so you can minimize your cache misses and storage seeks. This will improve total aggregate bandwidth and improve overall performance.

- Warren
 
  • #23
Thanks for the reply chroot. I will check into using threads correctly. Also is there no way to avoid the infinite while loop for server to keep listening? Wont it cause an CPU overhead with while(true)

Though I am a newbie here, one thing I would like to point out is that thread pool has an advantage over one-thread-per-client in terms of resource access/ control using mutex/ semaphores since all threads under the process share the resources. I guess on selectin between teh two...it depends on the requirement...
 
  • #24
karthik_br:

No, it will not cause any CPU utilization at all. When you call accept(), the operating system will block on the call until an event (a new network connection) occurs, then begin running your application again. It isn't an infinite loop -- it's a block. These are two different concepts.

- Warren
 
  • #25
chroot said:
Even though this is an ancient thread, I feel compelled to mention that haki is right, and you are wrong. What haki is describing is a thread pool; too bad he did not explicitly label the concept.
- Warren

Yes looking back it does seem like he was talking about a thread pool, i thought he was referring to a single thread since the OP was asking about whether to use a single or multiple threads.
 
  • #26
http://celestial.muux.org/viewtopic.php?f=18&t=16 [Broken]

This site has a insanly good tutorial on winsock

Its the best I've seen yet.
You have to sign up to view his stuff though.
His example uses threads as well to keep the server listening and revieving at the same time. Really good tutorial.
 
Last edited by a moderator:

1. What is a server-client loop in C/C++?

A server-client loop in C/C++ is a loop structure used to establish communication between a server and client in a network. The server is a computer or program that provides services to other computers or programs (clients) connected to it. The client is a computer or program that requests services from the server. The loop allows for continuous exchange of data between the server and the client.

2. How does a server-client loop work?

A server-client loop works by continuously looping through a set of instructions that allow the server to listen for and respond to client requests. The server first creates a socket, which is used to establish a connection with the client. It then uses the accept() function to wait for and accept incoming connections from clients. Once a connection is established, the server can send and receive data to and from the client using the send() and recv() functions. The loop continues until either the server or the client closes the connection.

3. What is the purpose of a server-client loop?

The purpose of a server-client loop is to enable communication between a server and client in a network. This allows for the exchange of data and services between multiple computers or programs. For example, a web server uses a server-client loop to respond to requests for web pages made by clients (web browsers).

4. Are there any challenges in implementing a server-client loop in C/C++?

Yes, there can be challenges in implementing a server-client loop in C/C++. One challenge is ensuring that the loop is properly synchronized, so that data is not lost or corrupted during transmission. Another challenge is handling errors and exceptions, such as when a client unexpectedly disconnects. Additionally, the server and client must agree on a protocol for communication, which can be difficult to design and implement.

5. Are there any alternatives to using a server-client loop in C/C++?

Yes, there are other options for establishing communication between a server and client. One alternative is using a messaging system, such as a message queue, where messages are sent and received asynchronously. Another option is to use a RESTful API, which allows clients to make HTTP requests to a server for data or services. However, a server-client loop is still a commonly used method for real-time communication between a server and client in a network.

Similar threads

  • Programming and Computer Science
Replies
7
Views
338
  • Programming and Computer Science
2
Replies
39
Views
5K
  • Programming and Computer Science
Replies
4
Views
2K
  • Programming and Computer Science
Replies
1
Views
2K
  • Programming and Computer Science
Replies
1
Views
2K
  • Engineering and Comp Sci Homework Help
Replies
4
Views
12K
  • Programming and Computer Science
Replies
9
Views
1K
Replies
7
Views
2K
  • MATLAB, Maple, Mathematica, LaTeX
Replies
3
Views
224
Back
Top