0

我正在开发一个使用 P(an)T(ilt)Z(oom) 摄像头跟踪对象的系统,该摄像头可以通过 HTTP 请求进行控制。我开发的 C 应用程序应该接收被跟踪物体的位置数据,并向相机发送命令以控制平移和倾斜角度。除了这些命令之外,摄像机还必须每 5 秒接收一次会话刷新命令。HTTP Digest Authorization 必须用于连接。

我正在使用 libcurl 发送 HTTP 请求。我已经发现对于摘要身份验证,需要在此 stackoverflow 帖子中的所有请求使用 on 和相同的 curl 句柄。
为了定期发送会话刷新命令,我尝试使用一个正在执行此操作的线程:

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 教程,现在我知道 在多个线程中使用一个 curl 句柄是不行的

我当时尝试的是使用带有 SIGALRM 的计时器来实现定期会话刷新。这并没有改变curl_easy_perform(curl). 奇怪的是,当发送普通命令来控制使用相同卷曲手柄的平移和倾斜位置时,应用程序不会崩溃。会话刷新和平移/倾斜命令之间的唯一区别是会话刷新使用 GET 而平移/倾斜使用 POST。

是否有任何其他可能性连续发送平移/倾斜命令,每 5 秒暂停一次,用于发送会话刷新?

4

2 回答 2

1

在一个小程序中你会遇到很多问题。这里有几个:

  1. 您可能会使用您使用的危险的无界 C 函数溢出那些固定大小的小型缓冲区之一。很可能其中之一是段错误的原因。
  2. curl_global_init() 被记录为被调用一次,你一遍又一遍地调用它——即使在两者之间没有调用 curl_global_cleanup() 也是如此。您显然在函数之外的某个地方调用 curl_easy_init() ,您应该将全局 init 移到那里。
  3. 'referer' 被填充了数据,但从未被使用过

另一个建议是使用 CURLOPT_ERRORBUFFER 而不是 curl_easy_strerror() 来获取错误消息,因为那时您可能会获得一些额外的细节。当然,在调试请求时设置 CURLOPT_VERBOSE 以查看事情是否符合您的要求。

于 2013-10-15T19:36:59.887 回答
0

感谢您的评论丹尼尔斯坦伯格。设置好句柄后,我现在curl_global_init()只调用一次。referer这里并不是真的需要,但我忘记在粘贴代码之前将其删除。

分段错误的原因是会话刷新命令和平移和倾斜命令试图同时使用一个相同的 curl 句柄,这显然不能真正起作用。所以计时器和 SIGALRM 的解决方案不是问题。分段错误已通过添加互斥锁来解决,以避免并发访问 curl 句柄。

于 2013-10-22T15:24:15.503 回答