35. curl: the easy/multi handle design and callback-driven I/O
What it is: the HTTP(S)/FTP/... client library behind nearly every language's HTTP bindings and an enormous share of embedded devices.
Concept mapping:
- Opaque handles:
CURL *curl = curl_easy_init();returns a pointer to a struct whose definition is private to curl's.cfiles — callers only ever see aCURL *and interact throughcurl_easy_setopt/curl_easy_perform/curl_easy_cleanup. This is Section 13'sstatic-for-privacy idea taken to the API level: the struct layout can change between curl versions without breaking binaries linked against it, because no caller code ever reads a field by name — this is Section 40's "designing a stable ABI," and it's why curl has kept API/ABI compatibility for over two decades. - Callback-driven I/O:
CURLOPT_WRITEFUNCTIONis exactly Section 11.2's function-pointer parameter — you hand curl a function pointer, and curl calls it with each chunk of the response body as it arrives, instead of you callingread()in a loop yourself:
size_t write_cb(char *ptr, size_t size, size_t nmemb, void *userdata) {
FILE *out = userdata;
return fwrite(ptr, size, nmemb, out); // return value tells curl how many bytes you consumed
}
// curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
// curl_easy_setopt(curl, CURLOPT_WRITEDATA, out_file);
- The multi interface (
curl_multi_*) is Section 21/23's event-loop idea applied to outgoing connections: instead of blocking on one request at a time (curl_easy_perform), the multi API lets one thread drive hundreds of concurrent requests through aselect()/poll()- style loop (curl_multi_fdset), the same non-blocking-I/O pattern as Redis'sae.cand Section 23.2's chat server, applied to a client instead of a server.