I tried my hand at C++ client/server programs, but they were extremely difficult, even with the "best tutorial" on the Web (Beej's). I could get a basic client/server program going, but it was with "blocking sockets", and all I knew how to do was get the server to send a one-line message every time a client connected. I didn't know how to get the server to perform a particular function depending on the request of the client.

An example of what I mean is:

If the client said "letters", the server would respond with "abcdef...." and if the client sent the message "numbers", the server would respond with "1234567890".

Also no idea how to get the server to manage connections with more than one user. What do you have to do, create an array of open sockets, and then when sending a message to all, use a standard for loop to send the message to socket[0], socket[1], etc?

Recommended Answers

All 5 Replies

I tried my hand at C++ client/server programs, but they were extremely difficult, even with the "best tutorial" on the Web (Beej's). I could get a basic client/server program going, but it was with "blocking sockets", and all I knew how to do was get the server to send a one-line message every time a client connected. I didn't know how to get the server to perform a particular function depending on the request of the client.

An example of what I mean is:

If the client said "letters", the server would respond with "abcdef...." and if the client sent the message "numbers", the server would respond with "1234567890".

Also no idea how to get the server to manage connections with more than one user. What do you have to do, create an array of open sockets, and then when sending a message to all, use a standard for loop to send the message to socket[0], socket[1], etc?

I don't know that you need more than one socket unless you have more than one client computer or more than one instance of this program running on a single client computer. You definitely don't need one socket per function.

You need a code for "letters" and a code for "numbers". It doesn't even need to be a code really. The message itself could simply be "letters" or "numbers", I suppose, though generally there's some numerical code for each function.

So set your socket up, then send a code for letters or numbers from the client to the server. The server gets the message and from that, decides what function to call, then it sends back the results on the socket to the client. If you can do socket programming for one possible function, you can do it for 500.

[EDIT]
My bad. Didn't notice the part about multiple users. One socket per client. I think if you're programming the sockets from scratch, there's no BROADCAST option, or at least you have to write that option yourself. And if either the client or the server can initiate the communication, then you need something a little more fancy than a plain old single socket that simply listens on the Server side. Possibly two sockets for each client, one for listening, one for sending.
[/EDIT]

Thanks for the reply.

So how exactly does that work?

The server has its recv() function within a while loop, and because its a blocking socket it will just sit at the recv until it gets a command? How does it handle the command after?

Lets look at it like this:

Client 1 connects to Server. Server receives "letters" from Client1, and then does something with the message.

--pseudo code--

while (program is running)
{
    receive data from connected client
    check if the message received says "letters"
    if (message is "letters") 
    {
         send "abcdefghijklmnopqrstuvwxyz"
    }
}

1. I think that pseudo code looks good but...where does it allow for the server to have another client connect?

2. How does the server maintain 2 socket connections?

3. How does the server send the data back to Client1, and not accidentally receive a message from Client 1 and send back to Client 2?

Thanks for the reply.

So how exactly does that work?

The server has its recv() function within a while loop, and because its a blocking socket it will just sit at the recv until it gets a command? How does it handle the command after?

Lets look at it like this:

Client 1 connects to Server. Server receives "letters" from Client1, and then does something with the message.

--pseudo code--

while (program is running)
{
    receive data from connected client
    check if the message received says "letters"
    if (message is "letters") 
    {
         send "abcdefghijklmnopqrstuvwxyz"
    }
}

1. I think that pseudo code looks good but...where does it allow for the server to have another client connect?

2. How does the server maintain 2 socket connections?

3. How does the server send the data back to Client1, and not accidentally receive a message from Client 1 and send back to Client 2?

It's been a few years, so I'm REALLY rusty. Worse, I've done sockets for several different projects with different needs, so with any luck I won't get 'em all mixed up. Hopefully someone else will chime in.

Number 3 is the easiest to answer. No two clients will share a socket. Each socket has a number and links exactly two computers. Thus if you're the server and you keep track of what socket belongs to what client computer, you can not worry about scenario number 3 at all.

You have a few scenarios. One, the server is normally idle and communication time is short. In that case, the socket is created, info is sent, then the socket is closed once the communication is done. For busier servers or servers where the communication will take longer, but the server needs to be available to other clients, the Server, when initially contacted on its main port, will immediately start a new process or thread, which sets up a second port, creates a socket to the client, and the communication takes place on the socket created by the new process or thread. Think of it as a big company. There's one main operator telephone operator number that everyone calls. The operator quickly takes the barest of info, then transfers you to a new person with a new phone number, thus keeping that main person and port clear. Same here.

So the upshot is:

  1. Multiple clients, usually idle, short comms, no big deal if a client can't connect --> Service one client at a time, then break the socket connection. Programming is much easier.
  2. Lots of clients, low idle time, must be able to handle clients connecting at same time ---> Much more involved. Create a new thread/process that handles most of the work, keep the main server port clear.

That's about the extent of my memory. My advice, tackle the first option if you can. It's much easier/less elaborate.

Thanks for the reply, but we are not on the same page unfortunately.

I am talking about persistent connections here. The client will have an open socket to the server for as long as the client wishes to remain connected.

"Number 3 is the easiest to answer. No two clients will share a socket. Each socket has a number and links exactly two computers. Thus if you're the server and you keep track of what socket belongs to what client computer, you can not worry about scenario number 3 at all."

I am about to graduate with a degree in Network Security. I understand how networks and sockets work, so that wasn't exactly what I was asking. I know very well how connections are maintained, how sockets work, IP and port, etc. I was actually trying to figure out HOW the server can keep track of which client is which. I have only done basic single client connections, so I don't know how to store variables that will let me know which client is which.

As for threading, I don't know threading AT ALL, so I'm screwed there.

And lastly, what about the concurrency of the situation. The psuedo-code above looked pretty good, but until the Server is done sending the message back to Client1 and can get back to the loop, every OTHER client sending messages will be discarded by the Server because it won't ever read them in. What do I do in that situation?


Do you have any better tutorials than Beej's guide? He talks in circles and doesn't explain well enough. I am doing Windows socket programming btw.

Thanks for the reply, but we are not on the same page unfortunately.

I am talking about persistent connections here. The client will have an open socket to the server for as long as the client wishes to remain connected.

"Number 3 is the easiest to answer. No two clients will share a socket. Each socket has a number and links exactly two computers. Thus if you're the server and you keep track of what socket belongs to what client computer, you can not worry about scenario number 3 at all."

I am about to graduate with a degree in Network Security. I understand how networks and sockets work, so that wasn't exactly what I was asking. I know very well how connections are maintained, how sockets work, IP and port, etc. I was actually trying to figure out HOW the server can keep track of which client is which. I have only done basic single client connections, so I don't know how to store variables that will let me know which client is which.

As for threading, I don't know threading AT ALL, so I'm screwed there.

And lastly, what about the concurrency of the situation. The psuedo-code above looked pretty good, but until the Server is done sending the message back to Client1 and can get back to the loop, every OTHER client sending messages will be discarded by the Server because it won't ever read them in. What do I do in that situation?


Do you have any better tutorials than Beej's guide? He talks in circles and doesn't explain well enough. I am doing Windows socket programming btw.

I know nothing about Windows socket programming. All I've ever done it on is Linux. Here's a decent Linux tutorial where I got this program from. Probably won't be too helpful for you, but I only post it to show the basic idea. It might be worth browsing at least, even though you're using Windows. I think that no matter what, you'll need to know how to create a new process, though not necessarily a new thread.

http://www.linuxhowtos.org/C_C++/socket.htm

The below code is for the server. It creates the server's main socket that the clients know about on line 27. That never closes or changes. It quickly creates a new socket on line 41, connecting the server to the client (my terminology may be messed up here, I'm not sure. It either creates a new socket or a new connection on the existing socket). It creates a new child process in line 45 that takes the new socket (again, not 100% sure on my terminology - connection" vs. "socket") and then it calls a function to do all the work. That function can take as long as it wants to do its job. Nothing's waiting for it to be done since it's in another process, so the main process can listen for new clients while the child process does the transfer. The transfer could take an hour. It doesn't matter.

As far as keeping track of the processes and the client socket connections, fork () and accept () both return numbers. That's what you keep track of regarding which process id and socket/connection belongs to which client.


The particular syntax is irrelevant to you since you're on Windows, but I imagine the concept is the same. You need to create a new process every time a client tries to connect and have IT do all the transferring so the parent process can handle new connections.

So you don't have to know anything about threading, but you do need to know about how to create a child process. You do that with fork () in Linux. I don' know how you do it in Windows.

/* A simple server in the internet domain using TCP
   The port number is passed as an argument 
   This version runs forever, forking off a separate 
   process for each connection
*/
#include <stdio.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>

void dostuff(int); /* function prototype */
void error(char *msg)
{
    perror(msg);
    exit(1);
}

int main(int argc, char *argv[])
{
     int sockfd, newsockfd, portno, clilen, pid;
     struct sockaddr_in serv_addr, cli_addr;

     if (argc < 2) {
         fprintf(stderr,"ERROR, no port provided\n");
         exit(1);
     }
     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     if (sockfd < 0) 
        error("ERROR opening socket");
     bzero((char *) &serv_addr, sizeof(serv_addr));
     portno = atoi(argv[1]);
     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons(portno);
     if (bind(sockfd, (struct sockaddr *) &serv_addr,
              sizeof(serv_addr)) < 0) 
              error("ERROR on binding");
     listen(sockfd,5);
     clilen = sizeof(cli_addr);
     while (1) {
         newsockfd = accept(sockfd, 
               (struct sockaddr *) &cli_addr, &clilen);
         if (newsockfd < 0) 
             error("ERROR on accept");
         pid = fork();
         if (pid < 0)
             error("ERROR on fork");
         if (pid == 0)  {
             close(sockfd);
             dostuff(newsockfd);
             exit(0);
         }
         else close(newsockfd);
     } /* end of while */
     return 0; /* we never get here */
}

/******** DOSTUFF() *********************
 There is a separate instance of this function 
 for each connection.  It handles all communication
 once a connnection has been established.
 *****************************************/
void dostuff (int sock)
{
   int n;
   char buffer[256];
      
   bzero(buffer,256);
   n = read(sock,buffer,255);
   if (n < 0) error("ERROR reading from socket");
   printf("Here is the message: %s\n",buffer);
   n = write(sock,"I got your message",18);
   if (n < 0) error("ERROR writing to socket");
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.