2013-10-15 3 views
0

Я разрабатываю систему, которая отслеживает объекты с помощью камеры P (an) T (ilt) Z (oom), которую можно контролировать с помощью HTTP-запросов. Предполагается, что приложение C, которое я разрабатываю, должно получать данные о местоположении отслеживаемого объекта и отправлять команды на камеру для управления углом панорамирования и наклона. В дополнение к этим командам камера должна получать команду обновления сеанса каждые 5 секунд. Авторизация HTTP-дайджест должна использоваться для подключения.Libcurl с авторизацией дайджеста в C: периодически отправлять HTTP-запросы

Я отправляю HTTP-запрос с помощью libcurl. Я уже понял, что для дайджест-аута нужно использовать и один и тот же ручок завитка для всех запросов in this stackoverflow post.
Для отправки команды обновления сеанса периодически я пытался использовать нить, которая просто делает это:

while(1) 
{ 
    usleep(5000000); 
    sessionContinue(g_Config.cam_ip); 
} 

С sessionContinue глядя, как это:

CURLcode sessionContinue(char* url) 
{ 
    CURLcode res; 
    char requestURL[40]; 
    char referer[47]; 
    struct curl_slist *headers=NULL; 

    strcpy(requestURL , url); 
    strcat(requestURL, CAM_SESSION_CONTINUE); 

    strcpy(referer , "Referer: http://"); 
    strcat(referer , url); 
    strcat(referer , CAM_MONITOR); 

    headers = curl_slist_append(headers,"Connection:keep-alive"); 
    headers = curl_slist_append(headers, camCookie); 

    // In windows, this will init the winsock stuff 
    curl_global_init(CURL_GLOBAL_ALL); 

    curl_easy_reset(curl); 
    if(curl) 
    { 
    // First set the URL that is about to receive our POST. This URL can 
    //just as well be a https:// URL if that is what should receive the 
    //data. 

    curl_easy_setopt(curl , CURLOPT_URL  , requestURL      ); 
    curl_easy_setopt(curl , CURLOPT_HTTPHEADER , headers       ); 
    curl_easy_setopt(curl , CURLOPT_HTTPGET , 1        ); 
    curl_easy_setopt(curl , CURLOPT_USERNAME , "root"       ); 
    curl_easy_setopt(curl , CURLOPT_PASSWORD , "password"      ); 
    curl_easy_setopt(curl , CURLOPT_HTTPAUTH , CURLAUTH_BASIC | CURLAUTH_DIGEST ); 

    // Perform the request, res will get the return code 
    res = curl_easy_perform(curl); 

    // Check for errors 
    if(res != CURLE_OK) 
     fprintf(stderr, "curl_easy_perform() failed @ %s:%d : %s\n", curl_easy_strerror(res) , __FILE__ , __LINE__); 
    } 

return res; 
} 

Приложение всегда разбился с ошибкой сегментации после выполнения curl_easy_perform(curl). Поэтому я снова прочитал учебник libcurl, и теперь я знаю, что using one curl handle in multiple threads is a no go.

То, что я пытался, было использовать таймер с SIGALRM для реализации периодического обновления сеанса. Это не изменило проблему с крахом на curl_easy_perform(curl). Странно то, что приложение не сбой при отправке обычной команды для управления позицией панорамирования и наклона, которая использует один и тот же ручок завитка. Единственная разница между командой session refresh и pan/tilt заключается в том, что обновление сеанса использует GET, а pan/tilt использует POST.

Есть ли еще какие-либо возможности для отправки команд панорамирования/наклона непрерывно с короткой паузой каждые 5 секунд, используемые для отправки обновления сеанса?

ответ

1

У вас есть большой круг проблем в одной небольшой программе. Вот несколько:

  1. Возможно, вы переполнили один из этих небольших фиксированных буферов с опасными неограниченными функциями C, которые вы используете. Вполне вероятно, что один из них является причиной segfault.
  2. curl_global_init() задокументирован как один раз, вы вызываете его снова и снова - это даже без вызова curl_global_cleanup() между ними. Вы явно вызываете curl_easy_init() где-то из функции, и вы должны переместить глобальный init там.
  3. «реферер» заполняется данными, но никогда не используется иначе

Другой совет заключается в использовании CURLOPT_ERRORBUFFER, чтобы получать сообщения об ошибках, а не в curl_easy_strerror(), как вы можете получить некоторые дополнительные детали тогда. И, конечно, установить CURLOPT_VERBOSE во время отладки запроса, чтобы увидеть, как все выглядит так, как вы этого хотите.

0

Спасибо за ваш комментарий Даниэль Стенберг. Теперь я вызываю curl_global_init() только один раз, когда ручка настроена. referer здесь не понадобятся, но я забыл удалить его, прежде чем вставлять код здесь.

Причина разлома сегментации заключалась в том, что команда обновления сеанса и команды для панорамирования и наклона пытались использовать один и тот же ручок завитка одновременно, что, очевидно, не может работать. Поэтому решение с таймером и SIGALRM не было проблемой. Дефекты сегментации были решены путем добавления блокировки мьютекса, чтобы избежать одновременного доступа к ручке завитка.

Смежные вопросы