Posts Tagged server
Simple Berkeley Sockets C Server Example
About Apache and Bloat
Every now and then I look at Apache and wonder about its size and complexity. Its a huge beastie now but absolutely brilliant too. I have quite a respect for it as do many around the world. But then I don’t really use very much of its functionality.
Sure its been re-factored into a modular form so that you only need to use the bits that you want but it still presents a mental preponderance thatmany would consider bloat. But bloat is a term used to describe software that has vast wads of unnessecary code that could be accomplished more simply. However Idon’t think that Apache has that. All of its code seems very purposeful, and as I indicated earlier it is reasonably easy to include or exclude as you will.
Introducing the Example
So this example is not here to show you the right way of doing things, but rather how simple the solution to you particular problem could be. In this case the example server simply serves up the time on the server machine to port 6543 for any client and then closes the stream. It can do this for many concurrent connections at once given the only complexity that is added to the server is client handling by forked process.
Now to the Code
/* -----------------------------------------------------------------------------
simple example of a server in C using very simple Berkeley sockets
This is just an example for looking at. Not really how you would actually
implement a server. For a start it does not take care of signals and isn't
capable of being implemented as a service.
----------------------------------------------------------------------------- */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <strings.h>
#include <arpa/inet.h>
/* we're not going to use arguments for this example */
#define SERV_UDP_PORT 6543
#define SERV_TCP_PORT 6543
#define SERV_HOST_ADDR "192.168.2.200"
int main (int argc, char ** argv, char ** env) {
int socket_server, socket_client, child_pid;
struct sockaddr_in address_client, address_server;
socklen_t client_address_size;
FILE *stream_client;
time_t now;
struct tm *tm;
/* open a tcp socket to listen on */
if ( (socket_server = socket(AF_INET, SOCK_STREAM, 0) ) < 0)
err_dump("server: can't open stream socket");
/* bind to our local address ans start listening so that clients can find us */
bzero((void *) &address_server, (size_t)sizeof(address_server));
address_server.sin_family = AF_INET;
address_server.sin_addr.s_addr = htonl(INADDR_ANY);
address_server.sin_port = htons(SERV_TCP_PORT);
if (bind(
socket_server,
(struct sockaddr *) &address_server,
sizeof(address_server))
< 0)
err_dump("server: can't bind local address");
listen(socket_server, 5);
for ( ; ; ) {
/* wait for client connection and accpt it when it comes */
client_address_size = sizeof(address_client);
socket_client = accept(
socket_server,
(struct sockaddr *) &address_client,
&client_address_size);
if (socket_client < 0)
err_dump("server: accept error");
if ( (child_pid = fork() ) < 0)
err_dump("server: fork error");
/* specific client process handling starts here */
else if (child_pid == 0) {
/* client process has no need of the server socket */
close(socket_server);
/* generate a file stream from the client socket */
if ((stream_client = fdopen(socket_client, "w")) == NULL) {
perror("daytimed fdopen");
return 5;
}
/* write to the client stream as per normal then close it */
if ((now = time(NULL)) < 0) {
perror("daytimed time");
return 6;
}
tm = gmtime(&now);
fprintf(stream_client, "%.4i-%.2i-%.2iT%.2i:%.2i:%.2iZ\n",
tm->tm_year + 1900,
tm->tm_mon + 1,
tm->tm_mday,
tm->tm_hour,
tm->tm_min,
tm->tm_sec);
fclose(stream_client);
exit(EXIT_SUCCESS);
/* client process has left the building */
}
/* the server has no need to keep the client socket open */
close(socket_client);
}
return 0;
}