一只小码农 2016-06-30 09:25 采纳率: 100%
浏览 2091
已结题

linux下libcurl异步收发问题

最近在使用libcurl异步收发消息时碰到一个问题,实在没头绪,有哪位大大可以帮忙看看,多谢
一、目标:使用multi interface实现消息异步收发,两个线程,一个线程发消息,另一个线程收消息
二、问题:
1、环回收发无问题,但是发送到其它IP有问题,抓包能建立TCP连接,但是马上会断开,没有发出数据
2、程序会发生段错误具体信息如下

(gdb) bt
#0  0x0000003d0e432222 in curl_multi_fdset (multi_handle=0x604120, read_fd_set=0x7ffff7fd4d00, write_fd_set=0x0, exc_fd_set=<value optimized out>, 
    max_fd=0x7ffff7fd4bfc) at multi.c:874
#1  0x0000000000400d08 in curl_multi_select (curl_m=0x604120) at curl_send.c:30
#2  0x0000000000400fb3 in curl_multi_recv () at curl_send.c:110
#3  0x0000003cf84079d1 in start_thread () from /lib64/libpthread.so.0
#4  0x0000003cf80e88fd in clone () from /lib64/libc.so.6
(gdb) f 0
#0  0x0000003d0e432222 in curl_multi_fdset (multi_handle=0x604120, read_fd_set=0x7ffff7fd4d00, write_fd_set=0x0, exc_fd_set=<value optimized out>, 
    max_fd=0x7ffff7fd4bfc) at multi.c:874
874 in multi.c
(gdb) f 1
#1  0x0000000000400d08 in curl_multi_select (curl_m=0x604120) at curl_send.c:30
30      curl_multi_fdset(curl_m, &fd_read, NULL, NULL, &max_fd);
(gdb) 

三、代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <curl/curl.h>

CURLM *g_curl_m = NULL;

int curl_multi_select(CURLM *curl_m)
{
    int    ret = 0;
    struct timeval timeout_tv;
    fd_set fd_read;
    fd_set fd_write;
    fd_set fd_except;
    int    max_fd = -1;

    if (NULL == curl_m)
    {
        return -1;
    }

    FD_ZERO(&fd_read);
    FD_ZERO(&fd_write);
    FD_ZERO(&fd_except);

    timeout_tv.tv_sec = 1;
    timeout_tv.tv_usec = 0;

    curl_multi_fdset(curl_m, &fd_read, NULL, NULL, &max_fd);
    if (-1 == max_fd)
    {
        return -1;
    }
    int select_ret = select(max_fd + 1, &fd_read, NULL, NULL, &timeout_tv);
    if (-1 == select_ret)
    {
        ret = -1;
    }
    else
    {
        ret = 0;
    }

    return ret;
}

size_t save_response(void *buffer, size_t size, size_t nmemb, void *userp)
{
    static int recv_times = 0;

    recv_times++;
    printf("recv response:\n%d\n", recv_times);
    printf("%s\n", buffer);

    return size * nmemb;
}

void curl_multi_send()
{
    int send_times = 0;
    int running_handle_count = 0;
    char auth[32] = {0};

    while(1)
    {
        CURL *easy_handle = NULL;
        struct curl_slist *http_header = NULL;

        send_times++;
        memset(auth, 0, sizeof(auth));

        easy_handle = curl_easy_init();
        snprintf(auth, sizeof(auth), "Authorization:%d", send_times);
        http_header = curl_slist_append(http_header, auth);
        http_header = curl_slist_append(http_header, "User-Agent: freecwmp");
        http_header = curl_slist_append(http_header, "Content-Type: text/xml");
        http_header = curl_slist_append(http_header, "Expect:");

        curl_easy_setopt(easy_handle, CURLOPT_URL, "http://guest:guest@10.55.0.156:9000/");
        curl_easy_setopt(easy_handle, CURLOPT_HTTPHEADER, http_header);
        curl_easy_setopt(easy_handle, CURLOPT_POSTFIELDS, "");

        curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, save_response);

        curl_multi_add_handle(g_curl_m, easy_handle);
        while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(g_curl_m, &running_handle_count))
        {
        }

        printf("Success send http msg.\n");
        usleep(10000000);
    }

    return;
}

void curl_multi_recv()
{
    int msgs_left = 0;
    int running_handles = 0;
    CURLM *curl_m = NULL;
    CURLMsg *msg = NULL;

    curl_m = g_curl_m;

    while(1)
    {
        if (0 == curl_multi_select(curl_m))
        {
            msgs_left = 0;
            running_handles = 0;

            while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(curl_m, &running_handles))
            {
            }

            while ((msg = curl_multi_info_read(curl_m, &msgs_left)))
            {
                if (CURLMSG_DONE == msg->msg)
                {
                    curl_multi_remove_handle(curl_m, msg->easy_handle);
                }
            }
        }
        usleep(100000);
    }

    return;
}

int main(int argc, char *argv[])
{
    curl_global_init(CURL_GLOBAL_ALL);
    g_curl_m = curl_multi_init();

    pthread_t send_pid = {0};
    pthread_t receive_pid = {0};
    //pthread_attr_t attr = {0};
    //pthread_attr_init(&attr);
    //pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    pthread_create(&receive_pid, NULL, (void *) curl_multi_recv, NULL);
    pthread_create(&send_pid, NULL, (void *) curl_multi_send, NULL);

    //pthread_attr_destroy(&attr);
    pthread_join(send_pid, NULL);
    pthread_join(receive_pid, NULL);

    curl_global_cleanup();

    return 0;
}
  • 写回答

1条回答 默认 最新

  • 关注

    这里贴官网的介绍:
    Handles. You must never share the same handle in multiple threads. You can pass the handles around among threads, but you must never use a single handle from more than one thread at any given time.
    官网说了,libcurl 的句柄最好不要在多个线程间共享,即使要传递参数,也要确保同时一个时刻只有一个线程在使用这个句柄。

    评论

报告相同问题?

悬赏问题

  • ¥15 本题的答案是不是有问题
  • ¥15 关于#r语言#的问题:(svydesign)为什么在一个大的数据集中抽取了一个小数据集
  • ¥15 C++使用Gunplot
  • ¥15 这个电路是如何实现路灯控制器的,原理是什么,怎么求解灯亮起后熄灭的时间如图?
  • ¥15 matlab数字图像处理频率域滤波
  • ¥15 在abaqus做了二维正交切削模型,给刀具添加了超声振动条件后输出切削力为什么比普通切削增大这么多
  • ¥15 ELGamal和paillier计算效率谁快?
  • ¥15 蓝桥杯单片机第十三届第一场,整点继电器吸合,5s后断开出现了问题
  • ¥15 file converter 转换格式失败 报错 Error marking filters as finished,如何解决?
  • ¥15 Arcgis相交分析无法绘制一个或多个图形