libcurl庫
有同步和異步兩種方式,而在本文中,重點(diǎn)放在異步方式,并使用epoll進(jìn)行socket事件管理。
Multi interface
在libcurl官方網(wǎng)站上提供了使用epoll進(jìn)行事件管理的例子。Example
步驟如下:
創(chuàng)建一個(gè)pipe,并用epoll來監(jiān)聽
初始化;得到multi指針
g.multi = curl_multi_init();設(shè)置multi的參數(shù)
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);
用來設(shè)置socket回調(diào)和timer回調(diào),sock_cb是socket的回調(diào)函數(shù),而multi_timer_cb是timeout之后的回到函數(shù)。
進(jìn)入while循環(huán),epoll_wait()監(jiān)聽事件
如果有連接進(jìn)來,epoll_wait()監(jiān)聽到fifofd,調(diào)用fifo_cb()函數(shù),讀取url,調(diào)用new_conn()函數(shù)
在new_conn()中,初始化easy handle句柄,設(shè)置easy句柄的傳輸選項(xiàng)
curl_easy_setopt(conn->easy, CURLOPT_WRITEFUNCTION, write_cb);
write_cb是在libcurl接收到數(shù)據(jù)之后調(diào)用的回調(diào)函數(shù),用來處理接收到的數(shù)據(jù)。
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指定的函數(shù)正常情況下每秒被libcurl調(diào)用一次,為了使CURLOPT_PROGRESSFUNCTION被調(diào) 用,CURLOPT_NOPROGRESS必須被設(shè)置為false,CURLOPT_PROGRESSDATA指定的參數(shù)將作為CURLOPT_PROGRESSFUNCTION指定函數(shù)的第一個(gè)參數(shù)。
使用curl_multi_add_handle()函數(shù)加入該easy句柄。這個(gè)函數(shù)會立刻觸發(fā)multi中設(shè)置的超時(shí)回調(diào)函數(shù),即
multi_timer_cb在
multi_timer_cb中調(diào)用curl_multi_socket_action(),該函數(shù)會執(zhí)行指定的action,建立連接。回調(diào)sock_cb()函數(shù),在set_sock()將fd添加到epoll中
epoll_wait()監(jiān)聽到事件,觸發(fā)event_cb(),action是EPOLLOUT,觸發(fā)curl_multi_socket_action()處理
可寫,觸發(fā)easy句柄中的write_cb()回調(diào)函數(shù)來處理接收到的數(shù)據(jù)。
// 11. 接收完畢之后,狀態(tài)變成EPOLLIN,觸發(fā)event_cb(),調(diào)用curl_multi_socket_action()處理