libcurl库
有同步和异步两种方式,而在本文中,重点放在异步方式,并使用epoll进行socket事件管理。
Multi interface
在libcurl官方网站上提供了使用epoll进行事件管理的例子。Example
步骤如下:
创建一个pipe,并用epoll来监听
初始化;得到multi指针
g.multi = curl_multi_init();
设置multi的参数
curl_multi_setopt(g.multi, CURLMOPT_SOCKETFUNCTION, sock_cb);
curl_multi_setopt(g.multi, CURLMOPT_SOCKETDATA, &g);
curl_multi_setopt(g.multi, CURLMOPT_TIMERFUNCTION, multi_timer_cb);
curl_multi_setopt(g.multi, CURLMOPT_TIMERDATA, &g);
用来设置socket回调和timer回调,sock_cb是socket的回调函数,而multi_timer_cb是timeout之后的回到函数。
进入while循环,epoll_wait()监听事件
如果有连接进来,epoll_wait()监听到fifofd,调用fifo_cb()函数,读取url,调用new_conn()函数
在new_conn()中,初始化easy handle句柄,设置easy句柄的传输选项
curl_easy_setopt(conn->easy, CURLOPT_WRITEFUNCTION, write_cb);
write_cb
是在libcurl接收到数据之后调用的回调函数,用来处理接收到的数据。
curl_easy_setopt(conn->easy, CURLOPT_NOPROGRESS, 0L);
curl_easy_setopt(conn->easy, CURLOPT_PROGRESSFUNCTION, prog_cb);
curl_easy_setopt(conn->easy, CURLOPT_PROGRESSDATA, conn);
CURLOPT_PROGRESSFUNCTION
指定的函数正常情况下每秒被libcurl调用一次,为了使CURLOPT_PROGRESSFUNCTION
被调 用,CURLOPT_NOPROGRESS
必须被设置为false,CURLOPT_PROGRESSDATA
指定的参数将作为CURLOPT_PROGRESSFUNCTION
指定函数的第一个参数。
使用curl_multi_add_handle()函数加入该easy句柄。这个函数会立刻触发multi中设置的超时回调函数,即
multi_timer_cb
在
multi_timer_cb
中调用curl_multi_socket_action()
,该函数会执行指定的action,建立连接。回调sock_cb()函数,在set_sock()将fd添加到epoll中
epoll_wait()监听到事件,触发event_cb(),action是EPOLLOUT,触发curl_multi_socket_action()处理
可写,触发easy句柄中的write_cb()回调函数来处理接收到的数据。
// 11. 接收完毕之后,状态变成EPOLLIN,触发event_cb(),调用curl_multi_socket_action()处理