在curl.c函数里面可以找到下面的这个结构体数组.这个数组就是注册所有协议的地方.
curl_multi_perform
->multi_runsingle
->Curl_connect
->setup_conn初始化连接
->parseurlandfillconn找到当前传入地址所使用的协议
->findprotocol把当前使用的协议与支持的协议数组里面的协议进行比较看是否相同,这样我们就找到了连接所用的协议
每种协议通过实现Curl_handler这个结构体里面的部分函数,再把它放入到这个结构体数组里面,这种协议就可以使用了.
static const struct Curl_handler * const protocols[] = {
#ifndef CURL_DISABLE_HTTP
&Curl_handler_http,
#endif
#ifndef CURL_DISABLE_FTP
&Curl_handler_ftp,
#endif
#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
&Curl_handler_ftps,
#endif
#ifndef CURL_DISABLE_TELNET
&Curl_handler_telnet,
#endif
#ifndef CURL_DISABLE_FILE
&Curl_handler_file,
#endif
#ifndef CURL_DISABLE_TFTP
&Curl_handler_tftp,
#endif
(struct Curl_handler *) NULL
};
协议调用过程:
curl_multi_perform
->multi_runsingle
->Curl_connect
->setup_conn初始化连接
->parseurlandfillconn找到当前传入地址所使用的协议
->findprotocol把当前使用的协议与支持的协议数组里面的协议进行比较看是否相同,这样我们就找到了连接所用的协议
例如在webkit中curl的使用,下面是我在阅读webkit代码时的一点记录:
writeCallback/headerCallback是怎么完成的:
Webkit使用lite注册了一个定时器,在使用main_loop的时候会执行这个定时器的回调函数.最后会调到curl_multi_perform,看下这次请求是否有数据需要读写。如果有的话由curl来控制不断传回数据直到结束。也就是说整个过程都是同步的,在这里会阻塞。当然阻塞是在curl里面的。
在ResourceHandleManager::downloadTimerCallback()中调用的curl_multi_perform:
while (curl_multi_perform(m_curlMultiHandle, &runningHandles) == CURLM_CALL_MULTI_PERFORM) { }
而这句话是错误的,我的意思是根本没有必要这么写。写成curl_multi_perform(m_curlMultiHandle, &runningHandles);就够了,没有必要要while因为这里的返回值绝对不会是CURLM_CALL_MULTI_PERFORM, 不相信我就看下这个函数的源码。
CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
{
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
struct Curl_one_easy *easy;
CURLMcode returncode=CURLM_OK;
struct Curl_tree *t;
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
easy=multi->easy.next;
while(easy != &multi->easy) {
CURLMcode result;
struct WildcardData *wc = &easy->easy_handle->wildcard;
if(easy->easy_handle->set.wildcardmatch) {
if(!wc->filelist) {
CURLcode ret = Curl_wildcard_init(wc); /* init wildcard structures */
if(ret)
return CURLM_OUT_OF_MEMORY;
}
}
do
result = multi_runsingle(multi, easy);
while (CURLM_CALL_MULTI_PERFORM == result);//它会在这里形成循环判断,所以不可能出现这个值,我的理解对吗?
if(easy->easy_handle->set.wildcardmatch) {
if(wc->state == CURLWC_DONE || result)
Curl_wildcard_dtor(wc);
}
if(result)
returncode = result;
easy = easy->next; /* operate on next handle */
}
do {
struct timeval now = Curl_tvnow();
multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
if(t) {
struct SessionHandle *d = t->payload;
struct timeval* tv = &d->state.expiretime;
tv->tv_sec = 0;
tv->tv_usec = 0;
}
} while(t);
*running_handles = multi->num_alive;
if( CURLM_OK >= returncode )
update_timer(multi);
return returncode;
}