Hello,
I try to use libmicrohttpd in conjunction with a main function which
acquires data in an endless loop (currently every 4 seconds).
What I want to achieve is that all the current client connections
with an active request for this data will block until it is
available.
Thus I decided to go for the MHD_USE_THREAD_PER_CONNECTION model.
I tried to use pthread_cond_wait and pthread_cond_broadcast to
implement the blocking scheme, but unfortunately this does not work
as expected when more than one client is in use.
Attached is a broken down example code.
compile with:
cc -o httpd-test -g -Wall -W httpd-test.c -lmicrohttpd
As a client I currently use a
couple of "wget -q -O - http://localhost:8888" calls.
Any hint?
Sven
--
/* Fuck me gently with a chainsaw... */
(David S. Miller in /usr/src/linux/arch/sparc/kernel/ptrace.c)
/me is giggls@ircnet, http://sven.gegg.us/ on the Web
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include <microhttpd.h>
#include <pthread.h>
#define DELAY 4
#define UNUSED(expr) do { (void)(expr); } while (0)
float cur_val;
pthread_cond_t cv;
pthread_mutex_t mutex;
int nrclients=0;
static int answer_to_connection(void * cls,
struct MHD_Connection * connection,
const char * url,
const char * method,
const char * version,
const char * upload_data,
size_t * upload_data_size,
void ** ptr) {
static int dummy;
static char statedata[1024];
struct MHD_Response * response;
int ret;
// ignore explicitely unused parameters
// eliminate compiler warnings
UNUSED(cls);
UNUSED(url);
UNUSED(version);
UNUSED(upload_data);
UNUSED(upload_data_size);
if (0 != strcmp(method, "GET"))
return MHD_NO; /* unexpected method */
if (&dummy != *ptr) {
/* The first time only the headers are valid,
do not respond in the first round... */
*ptr = &dummy;
return MHD_YES;
}
*ptr = NULL; /* clear context pointer */
nrclients++;
printf("pthread_cond_wait\n");
pthread_cond_wait(&cv, &mutex);
nrclients--;
snprintf(statedata,1024,
"cur_val=\"%5.1f\";\n",
cur_val);
response = MHD_create_response_from_data(strlen(statedata),
(void*) statedata,
MHD_NO,
MHD_NO);
MHD_add_response_header(response,
"Content-Type", "text/javascript");
ret = MHD_queue_response(connection,
MHD_HTTP_OK,
response);
MHD_destroy_response(response);
return ret;
}
int main() {
unsigned first;
struct MHD_Daemon *daemon;
first=1;
while (1) {
cur_val=42;
if (first) {
daemon = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION,
8888,
NULL,
NULL,
&answer_to_connection,
NULL,
MHD_OPTION_END);
if (daemon == NULL) {
fprintf(stderr,"unable to run HTTP Server!\n");
exit(EXIT_FAILURE);
}
first=0;
} else {
if (nrclients >0) {
/* push values to clients */
printf("pthread_cond_broadcast (%d)\n",nrclients);
pthread_cond_broadcast(&cv);
}
}
printf("acquire data here...\n");
sleep(DELAY);
}
MHD_stop_daemon (daemon);
exit(EXIT_SUCCESS);
}