Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Connection failure error occurs in high concurrency scenario #208

Open
zhangsen1860 opened this issue Dec 14, 2021 · 3 comments
Open

Connection failure error occurs in high concurrency scenario #208

zhangsen1860 opened this issue Dec 14, 2021 · 3 comments
Labels

Comments

@zhangsen1860
Copy link

Hello @babelouest , I tested ulfius in multithreading scenario, I created some threads and each thread connected the server 1000 times, when the number of threads increased to 1000, the connection failure error occured, error code is 5. Below is my test code:

///////////////////////////////////////////////////////////////////////////////
//client.c
///////////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <string.h>
#include "ulfius.h"
#include "pthread.h"

static void get_msg_from_response(struct _u_response* response, char** res){
if(NULL != response){
res = (char)calloc(response->binary_body_length + 1, 1);
memcpy(*res, response->binary_body, response->binary_body_length);
}
}

void fun(void args){
int i = 0, res = 0;
int times = (int)args;
char url[256] = { 0 };
char
res_msg = NULL;
struct _u_request request;
struct _u_response response;
char *req_str = "123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100";

sprintf(url, "http://127.0.0.1:20000");
while(i < times){
    ulfius_init_request(&request);
    ulfius_init_response(&response);

    ulfius_set_request_properties(&request,
               U_OPT_HTTP_VERB, "POST",
               U_OPT_HTTP_URL, url,
               U_OPT_HTTP_URL_APPEND, "/test/thread",
               U_OPT_TIMEOUT, 20,
               U_OPT_BINARY_BODY, req_str, o_strlen(req_str),
               U_OPT_HEADER_PARAMETER, "Content-Type", "application/json",
               U_OPT_NONE);

    res = ulfius_send_http_request(&request, &response);
    if(res != U_OK){
        printf("Communication error! error code = %d.\n", res);
    }

    get_msg_from_response(&response, &res_msg);
    printf("Server response:%s.\n", res_msg);

    ulfius_clean_response(&response);
    ulfius_clean_request(&request);
    if(res_msg){
        free(res_msg);
        res_msg = NULL;
    }
    i++;
}

}

int mult_thread_testing(int thread_num, int times){
int num = 0;
int t = 0;
t = times;
while(num < thread_num){
//usleep(200000);
pthread_t thread_id;
pthread_create(&thread_id, NULL, (void*)fun, &t);
pthread_detach(thread_id);
num++;
}
getchar();
return 0;
}
int main(int argc, char** argv){
if (argc < 2) {
getchar();
return 0;
}

if (!strcmp(argv[1], "thread_test")) {
    printf("-------------Thread Testing-------------\n");
    if (argc < 4) {
        printf("-------------cThread Testing args error, need threads num, times--------------\n");
        return 0;
    }
    mult_thread_testing(atoi(argv[2]), atoi(argv[3]));
    return 0;
}

}

///////////////////////////////////////////////////////////////////////////////
//server.c
///////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <string.h>
#include "ulfius.h"

void get_msg_from_request(const struct _u_request * request, char **res) {
if (NULL != request) {
res = (char)calloc(request->binary_body_length + 1, 1);
memcpy(*res, request->binary_body, request->binary_body_length);
}
}

int callback_test_thread(const struct _u_request * request, struct _u_response * response, void * user_data) {
char* req_str = NULL;

get_msg_from_request(request, &req_str);
printf("Request data from client:\n %s.\n", req_str);

ulfius_set_string_body_response(response, 200, "Receive data success");
if(req_str){
free(req_str);
req_str = NULL;
}
return U_CALLBACK_CONTINUE;
}

int main(){
int res = 0;
struct _u_instance instance;
res = ulfius_init_instance(&instance, 20000, NULL, NULL);
if(res != U_OK){
printf("Init instance failed, error code = %d.\n", res);
}
ulfius_add_endpoint_by_val(&instance, "POST", "/test/thread", NULL, 0, &callback_test_thread, NULL);
res = ulfius_start_framework(&instance);
if(res == U_OK){
printf("Start framwork success!\n");
while(1){
sleep(1);
}
}else{
printf("Start Rest Server: Error starting framework, error code = %d.\n", res);
}
ulfius_stop_framework(&instance);
ulfius_clean_instance(&instance);
return res;
}
///////////////////////////////////////////////////////////////////////////////

Does ulfius have a limit on the number of threads, or there are some problem in my code?

@babelouest
Copy link
Owner

Hello @zhangsen1860 ,

Ulfius is based on libmicrohttpd for the low-level http management, including network connections.

More specifically, it uses the mhd flags MHD_USE_THREAD_PER_CONNECTION and MHD_USE_INTERNAL_POLLING_THREAD for the multi thread parameters.

I don't know specifically what is the thread limit for an ulfius instance, but of course every ulfius instance has a limit on the number of threads it can open, based on libmicrohttpd and the system beneath.

Here are some quick searches about libmicrohttpd threads management:

Here is your example programs patched to work, and if make a quick test, I come to the limit with the following options:

$ ./client thread_test 340 10

This seems to be the limit on my side.

If you need to calculate the thread limit for a program, I suggest you run the client and the server on different machines, otherwise the client would use resources that could be used by the server, and the tests would lack precision.

zhangsen1860.tar.gz

@zhangsen1860
Copy link
Author

Sorry to reply so late, I will study the libmicrohttpd and test again.

@babelouest
Copy link
Owner

Hello @zhangsen1860 , any update on your tests?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants