Apache Portable Runtime (APR) Threaded socket server
I have been playing around with APR for the last few days for a project I am working on. I couldn’t find an example of a threaded socket server using APR sockets and threads so here is one that will hopefully help you.
Big thanks to http://dev.ariel-networks.com/apr/apr-tutorial/html/apr-tutorial.html most of the code comes from his tutorials
#include <stdio.h>
#include <stdlib.h>
//APR Includes
#include <apr_general.h>
#include <apr_pools.h>
#include <apr_file_io.h>
#include <apr_strings.h>
#include <apr_network_io.h>
#include <apr_thread_proc.h>
/* default listen port number */
#define DEF_LISTEN_PORT 8081
/* default socket backlog number. SOMAXCONN is a system default value */
#define DEF_SOCKET_BACKLOG SOMAXCONN
/* default buffer size */
#define BUFSIZE 4096
static void* APR_THREAD_FUNC processConnection(apr_thread_t *thd, void *);
int listenServer(){
//Setup a socket to listen on the address for incoming requests
apr_socket_t *listenSocket;
apr_pool_t *memPool;
apr_status_t retStatus;
apr_threadattr_t *thd_attr;
apr_sockaddr_t *sa;
apr_pool_create(&memPool, NULL);
apr_threadattr_create(&thd_attr, memPool);
retStatus = apr_sockaddr_info_get(&sa, NULL, APR_INET, DEF_LISTEN_PORT, 0, memPool);
if (retStatus != APR_SUCCESS) {
goto error;
}
retStatus = apr_socket_create(&listenSocket, sa->family, SOCK_STREAM, APR_PROTO_TCP, memPool);
if (retStatus != APR_SUCCESS) {
goto error;
}
apr_socket_opt_set(listenSocket, APR_SO_NONBLOCK, 0);
apr_socket_timeout_set(listenSocket, -1);
apr_socket_opt_set(listenSocket, APR_SO_REUSEADDR, 1);
retStatus = apr_socket_bind(listenSocket, sa);
if (retStatus != APR_SUCCESS) {
goto error;
}
retStatus = apr_socket_listen(listenSocket, DEF_SOCKET_BACKLOG);
if (retStatus != APR_SUCCESS) {
goto error;
}
while (1) {
apr_socket_t *ns;/* accepted socket */
retStatus = apr_socket_accept(&ns, listenSocket, memPool);
if (retStatus != APR_SUCCESS) {
goto error;
}
apr_socket_opt_set(ns, APR_SO_NONBLOCK, 0);
apr_socket_timeout_set(ns, -1);
//Create the new thread
apr_thread_t *thd_obj;
retStatus = apr_thread_create(&thd_obj, NULL, processConnection, ns, memPool);
if(retStatus != APR_SUCCESS){
printf("Error Creating new Thread\n");
}
}
apr_pool_destroy(memPool);
apr_terminate();
return 0;
error:
{
char errbuf[256];
apr_strerror(retStatus, errbuf, sizeof(errbuf));
printf("error: %d, %s\n", retStatus, errbuf);
}
apr_terminate();
return -1;
}
static void* APR_THREAD_FUNC processConnection(apr_thread_t *thd, void* data){
apr_socket_t * sock = (apr_socket_t*) data;
while (1) {
char buf[BUFSIZE];
apr_size_t len = sizeof(buf) - 1;/* -1 for a null-terminated */
apr_status_t rv = apr_socket_recv(sock, buf, &len);
if (rv == APR_EOF || len == 0) {
printf("Socket Closed\n");
apr_socket_close(sock);
break;
}
if(len > 0){
printf("Read: %s\n", buf);
}
buf[len] = '\0';/* apr_socket_recv() doesn't return a null-terminated string */
}
}