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");
}