client/server architecture with multiple clients - c

I need to implement a server/client code in C.
Server needs to be able to accept exactly four connections at the time.
I can't get this working. What I've done so far:
1. create a socket
2. set it to non-blocking: fcntl(sock,F_SETFL, O_NONBLOCK);
3. bind it
4. listen: listen(sock, 4);
The part which I am not quite sure about is how to accept the client's connection. My code looks something like this:
while (1) {
if ((sockfd = accept(sock, (struct sockaddr *) &client_addr, &client_size)) < 0) {
perror("Error\n");
}
read(sockfd, &number, sizeof(number));
write(sockfd, &number, sizeof(number));
}
When I execute client and server code, client seems to be writing something to the socket, which server never receives and the entire execution blocks.
What is the proper way to accept connections from multiple clients?

One basic workflow for this kind of server, if you don't want to use multithreading, is like this:
Create an fd_set of file descriptors to watch for reading
Open a socket
Bind the socket to a port to listen on
Start listening on the socket
Add the socket's file descriptor to the fd_set
While not done
Use select to wait until a socket is ready to read from
loop through the fds in your fd_set that have data available
If the current fd is your listening socket, accept a new connection
Else, it's a client fd. Read from it, and perhaps write back to it.
This page shows a flowchart of the above process. (Scroll down for a very nicely annotated example.)
This page is chock full of examples for select.

You should look the man of select. It will tell you when and which sockets are ready to write/read

Related

Socket in C: Proper way to close socket

I often see sample codes for a server program using socket.
(For simplicity, here I don't check return values of functions such as socket() or bind() etc.)
int sockfd = 0, newsockfd = 0;
struct sockaddr_in address;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
bind(sockfd, (struct sockaddr*)&address, sizeof(address));
listen(sockfd, 1);
newsockfd = accept(sockfd, (struct sockaddr*)NULL, NULL);
... do some communication ...
close(newsockfd);
Most of sample codes I found on the web have close(newsockfd) but don't have close(sockfd).
My question is whether it is really correct NOT to close sockfd.
If it's correct, I want to know why.
My understanding is that sockfd is one of the file descriptors and
it seems to have no reason to quit program without closing it.
More specifically, I'm wondering that not-closing-sockfd can cause the bind error (e.g. this socket is aready in use...) when the program works next time.
I really appreciate if you help me.
Thank you for your time.
Resources allocated by the application, like memory or open file descriptors (which includes sockets) will be automatically freed by modern OS if the program exits. Thus, if the server socket should be available throughout the whole program (in order to accept connections) it is fine to not explicitly close it but let the OS do this when the application exits.
You should always close sockfd when you stop the listening.
Two reasons why some developers do not care very much about not closing sockfd:
If your program quits without closing it, the OS will close sockfd for you
Most of the time, servers keep the listening open all the time (eg: for months)
However if your program launches a listening socket on some event, then closes it after a while, and loops, then you must close the sockfd, to prevent an error EADDRINUSE (Address already in use) at next iteration, and a memory leak.
Besides, the error EADDRINUSE (Address already in use) may occur on other circumstances that I do not detail here.
sockfd act as a server socket: it is used only to accept more and more incoming connections. You keep sockfd opened, bound and listening as long as you have to accept and handle new connections on newsockfd, wich hold the current connection on wich you are reading/writing from/to some peer program. When done with newsockfd you close it and, if requiref, accept a new one with accept() on sockfd. And so on.

C sockets - keeping pool of connections for reuse - s

I am writing a two daemon application - a client and a server. It is a very basic version of distributed shell. Clients are connecting to the server, and server issues a command, that is propagated to every client.
I dont know how to create the socket logic on server-side - I do some testing and for now I am accepting connections in an loop and for every incoming connection I fork a child to process the connection
while (1) {
clisockfd = accept(sockfd, (struct sockaddr *) &cliaddr, &clilen);
if (clisockfd < 0) {
log_err("err on opening client socket");
exit(EXIT_FAILURE);
}
/* create a new child to process the connection */
if((pid = fork()) < 0) {
log_err("err on forking, something is really broken!");
exit(EXIT_FAILURE);
}
if(!pid) {
/* here we are in forked process so we dont need the sockfd */
close(sockfd);
/* function that handles connection */
handle_connection(clisockfd);
exit(EXIT_FAILURE);
} else {
close(clisockfd);
}
}
However what I have now have some disadvantages - I can accept a connection, do something with it, and return to main process (forked process have to return, and then execution in main process is resumed). I would like to keep every socketfd somewhere(a list?) and be able to choose one of those (or all of them) and send to this socketfd a command that I want to issue on my client/s. I assume that I cant do it in traditional accept->fork->return to main process manner.
So it probably should looks like:
client connects -> server set up a new socketfd and saves it somewhere -> drops to shell where I can choose one of socket and send it a command -> somewhere in the whole process it also should wait for next incoming client connections - but where?
If someone could give me an idea what mechanisms should I use to create the logic that I need? Maybe it would be better to issue connection from server to client, not from client to server.
Regards,
Krzysztof
I assume that I cant do it in traditional accept->fork->return to main process manner.
You could but it will be hard to design/maintain.
The best solution is to use select() (POSIX), epoll() (Linux), kqueue() (BSD) or I/O Completion Ports (Windows) depending on your platform.
There is a good examples/explanations about select() in Beej's network programming guide.

Use semaphores for handling sockets in C

I have the following piece of code:
SOCKET sock = open_socket(szListenHost, iListenPort);
if (sock > 0) {
SOCKET client;
struct sockaddr_in peeraddr;
T_socklen len = sizeof (struct sockaddr_in);
char buf[1024];
sin.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
sin.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
sin.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
sin.hStdError = GetStdHandle(STD_ERROR_HANDLE);
sin.wShowWindow = SW_HIDE;
dwCreationFlags = CREATE_NO_WINDOW;
CreateProcess(NULL, buf, NULL, NULL, FALSE, dwCreationFlags,
NULL, NULL, &sin, &pin);
memset(&peeraddr, 0, sizeof (struct sockaddr_in));
client = accept(sock, (sockaddr*)&peeraddr, &len);
if (client > 0) {
rv = message_loop(client);
}
closesocket(sock);
}
As you can see, this is opening a TCP socket for interrogation reasons.
The situation is the following: my client application (who is opening those sockets) might need to open different TCP sockets simultaneously, which might cause problems.
In order to avoid those problems, I would like to ask whether the socket is already opened. If yes, then wait until the socket is freed again and then try again to open the socket.
I have understood that semaphores can be used for this intention, but I have no idea how to do this.
Can anybody help me?
Thanks
First I'd like to thank John Bollinger for your fast response. Unfortunately their seems to be as misunderstanding: I am not looking for a way to open one socket different times simultaneously, but I am looking for a way to be noticed when a socket becomes available. In fact, I would like to do the following: Instead of:
SOCKET sock = open_socket(szListenHost, iListenPort);
I could do this (very basically):
while (open_socket(szListenHost, iListenPort)) {sleep (1 second;)}
This however means that I would need to poll the socket constantly, creating quite some overhead. I have heard that semaphores could solve this issue, something like:
SOCKET sock = handle_semaphore(open_socket(szListenHost, iListenPort));
and the "handle_semaphore" would then be a system that automatically waits for the socket to be released, so that immediately my client process can open the socket, without the risk of being pushed behind. As you can see, it's all about rumours but I have no idea how to realise this. Does anybody know whether indeed semaphores can be used for this intention and if possible, give me some guidance on how to do this?
Thanks
Once opened, a socket cannot be reopened, even if it is closed. You can create a similar, new socket, though. Either way, it is difficult to reliably determine whether a previously-opened socket has been closed, except by closing it.
In any case, the usual paradigm does not require the kind of coordinating mechanism you ask about. Normally, one thread of one process would open the socket and have responsibility for accepting connections on it. If it is desired that the program be able to handle more than one connection at a time, then each time that thread accepts a new connection, it assigns that connection to be handled by another thread or process -- typically, but not necessarily, a newly-created one.
It is not usually necessary or desirable to open a new socket to receive additional connections at the same address and port. Usually you just use the same socket, without caring about the state of any connections already established via that socket. You could, perhaps, use a semaphore to coordinate multiple threads of the same process receiving connections from the same socket, but I would avoid that if I were you.
Meanwhile the situation has changed, and I now have been able to add semaphores to my socket related application. Generally this works but sometimes the application hangs.
After some debugging I have understood that the application hangs at the moment I launch following C command:
printf("Will it be accepted?\n");
fflush(stdout);
memset(&peeraddr, 0, sizeof (struct sockaddr_in));
client = accept(sock, (sockaddr*)&peeraddr, &len);
printf("It is accepted, the client is %d.\n",client);
=> I can see in my debug log "Will it be accepted?", but I don't see "It is accepted, ...".
I admit that I am quite violent while testing (sometimes I stop debugging sessions without giving the application to close the socket, ...), but you can imagine customers behaving in the same way, to the application needs to be sufficiently robust.
Does anybody know how I can avoid the "accept" command going into such an infinite loop?
Thanks

Accept multiple subsequent connections to socket

I have a listener that will pass arbitrary data, HTTP requests, to a network socket which is then delivered over TCP. This works fine for the first request but the listener does not accept subsequent new requests.
My question is:
If I have sock=accept(listener,(struct addr *)&sin, &sinlen); then, based on the socket function reference, the listener socket remains open and I should be able to re-call accept() any number of times for subsequent requests. Is this correct? If so, can someone more familiar than I with socket programming please explain how this code might look?
Yes, you can accept() many times on the listening socket. To service multiple clients, you need to avoid blocking I/O -- i.e., you can't just read from the socket and block until data comes in. There are two approaches: you can service each client in its own thread (or its own process, by using fork() on UNIX systems), or you can use select(). The select() function is a way of checking whether data is available on any of a group of file descriptors. It's available on both UNIX and Windows.
Here is a simple example from Beej's Guide to Network Programming.
while(1) { // main accept() loop
sin_size = sizeof their_addr;
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if (new_fd == -1) {
perror("accept");
continue;
}
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *)&their_addr),
s, sizeof s);
printf("server: got connection from %s\n", s);
if (!fork()) { // this is the child process
close(sockfd); // child doesn't need the listener
if (send(new_fd, "Hello, world!", 13, 0) == -1)
perror("send");
close(new_fd);
exit(0);
}
close(new_fd); // parent doesn't need this
}
The child process — after the fork() — handles the communication asynchronously from accept()ing further connections in the parent.
Yes, you have the right general idea.
While my C socket programming is a bit rusty, calling accept on a server socket sets up the communications channel back to the client side of the socket. Calling accept on future connection attempts will set up multiple socket channels.
This means that one should take care to not overwrite a single shared structure with a specific connection's data, but it doesn't sound like that's the kind of error you would be prone to make.

Can the server use the same socket to send the response to the client? how?

I am using Berkeley sockets (both: Internet domain and Unix domain) and I was wondering if the server can use the same sockets for reading the request and writing a response to the client. Or should the client create an other socket to wait for the replay and the server connect to it after processing the message received.
By the way, I am talking about connection oriented sockets (stream sockets, TCP, ...).
This is the simplified server code (I ommit error checking on system calls here just for simplicity):
int main() {
int server_socket, connected_socket;
struct sockaddr_in server_addr;
char buf[1024];
char aux[256];
int bytes_read;
server_socket = socket(AF_INET, SOCK_STREAM, 0);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(1234);
bind(server_socket, &server_addr, sizeof(server_addr))
listen(server_socket, 5)
connected_sodket = accept(server_socket, 0, 0);
do {
bzero(buf, sizeof(buf));
bytes_read = read(connected_socket, buf, sizeof(buf));
} while (bytes_read > 0);
/* Here I want to use connected_socket to write the reply, can I? */
close(connected_socket);
close(server_socket);
return (EXIT_SUCCESS);
}
And this is the simplified client code (I ommit error checking on system calls here just for simplicity):
int main() {
int client_socket;
struct sockaddr_in server_addr;
client_socket = socket(AF_INET, SOCK_STREAM, 0);
hp = gethostbyname("myhost");
server_addr.sin_family = AF_INET;
memcpy(&server_addr.sin_addr, hp->h_addr_list[0], hp->h_length);
server_addr.sin_port = htons(1234);
connect(client_socket, &server_addr, sizeof(server_addr));
write(client_socket, MSG, sizeof(MSG));
/* Here I want to wait for a response from the server using client_socket, can I? */
close(client_socket);
return (EXIT_SUCCESS);
}
Can I use connected_socket in the server and client_socket in the client to pass a response message back? Or should I use the client address I get in the server when in "accept" to connect to a socket in the client?
I have tried by using read/wrint in the client/server where the comment is shown but that way both programs keep blocked, it seems to be a dead-lock.
Thanks ins advance!
Regards.
You should use the same socket!
Your application protocol defines unambiguously when the client and the server should wait for data or send messages to each other; assuming a protocol with only one request from the client and one response from the server, the following should hold:
The client establishes a connection with the server;
the client sends its request (with send());
the client knows, by virtue of the protocol, that the server will reply; therefore it waits for data on the same socket (recv());
after validating the response, the client can close the socket.
The server accepts a connection from the client;
the server knows that the first step is up to the client, hence it waits for data (recv());
the server validates the request;
the server now knows, from the protocol, that the client is waiting for data; hence it sends its response with send();
the server knows, from the protocol, that there are no further steps; hence it can close the socket.
You can use the same socket BUT your program is set up to have the server read EVERYTHING the client sends before attempting to reply. So the loop in the server won't complete until the client closes the write side of its socket so the server gets an EOF (0 bytes read), and thus the server will never send back its response.
There are a couple of ways you can deal with this.
You can break the loop in the server after its seen the whole request, rather than reading until EOF. This requires that the data sent by the client be self-delimiting somehow, so the server can know when its read it all.
You can use a second connection for the reply. Probably not the best.
You can use asymmetric shutdown of the socket. Have the client do shutdown(client_socket, SHUT_WR) to half-close the socket. The server will then see the EOF (and the loop will finish), but the other direction on the socket will still be open for the reply.
Yes, it's possible. Look check out this page for an example of a simple server (and simple client). Note that the server typically passes the "accept"ed file descriptor into a new process so that it can continue listening for more incoming connections
Not only should you use the same socket (as Federico says), you actually have to in order to get your return packets through firewalls.
Firewalls know about TCP connections, and automatically allow the return data to pass through if a machine inside the firewall initiated the connection. If instead you tried to create a new TCP socket from the outside the firewall would block it unless that traffic was specifically permitted.
Yes, SOCK_STREAM sockets are two-way. You should be able to read and write to/from the same socket on each side of the connection. The man page for socket(2) has more detail on this.
Yes, you can. TCP sockets are bi-directional. Just use the same read() and write() functions. Also make sure to check for error conditions on all calls to connect(), read(), write(), ... as you can't control what happens on the network.
Sorry; I did not say it but I did try it like this
This code in the server where the comment is:
write(connected_socket, "Ok, I got it", sizeof("Ok, I got it"));
and this code in the client where the comment is:
read(client_socket, buf, sizeof(buf));
Both programs keep blocked and when I kill the client, the server shows the messages it received (I have a printf just after the server calls read).
I try it with send and recv (both with 0 flags) instead of read and write and it did not change.
In your current setup the server tries to read until the client closes the socket, while the client doesn't close the socket until the server answered. Therefore you have a kind of "deadlock". The server is not stopping to read in the hope some more data might arrive and the client has no way to tell the server it is done.
You need some way for the server to recognize that the request is complete, while the connection is still open. If you for example terminate your request by a newline, the server can check if it received a full line and then stop reading and send the answer.
Have you tried it? It looks like it should work when you actually put the code in where indicated

Resources