curl_easy_recv: Improve documentation and example program

Follow-up to 82245ea: Fix the example program sendrecv.c (handle
CURLE_AGAIN, handle incomplete send). Improve the documentation
for curl_easy_recv() and curl_easy_send().

Reviewed-by: Frank Meier
Assisted-by: Jay Satiro

See https://github.com/curl/curl/pull/1134
This commit is contained in:
Michael Kaufmann 2016-12-18 12:51:48 +01:00
parent 82245eaa56
commit afff64dbcd
6 changed files with 98 additions and 59 deletions

View file

@ -62,10 +62,9 @@ int main(void)
CURLcode res;
/* Minimalistic http request */
const char *request = "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n";
curl_socket_t sockfd; /* socket */
long sockextr;
size_t iolen;
curl_off_t nread;
size_t request_len = strlen(request);
curl_socket_t sockfd;
size_t nsent_total = 0;
/* A general note of caution here: if you're using curl_easy_recv() or
curl_easy_send() to implement HTTP or _any_ other protocol libcurl
@ -82,54 +81,76 @@ int main(void)
curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L);
res = curl_easy_perform(curl);
if(CURLE_OK != res) {
printf("Error: %s\n", strerror(res));
return 1;
}
/* Extract the socket from the curl handle - we'll need it for waiting.
* Note that this API takes a pointer to a 'long' while we use
* curl_socket_t for sockets otherwise.
*/
res = curl_easy_getinfo(curl, CURLINFO_LASTSOCKET, &sockextr);
if(CURLE_OK != res) {
if(res != CURLE_OK) {
printf("Error: %s\n", curl_easy_strerror(res));
return 1;
}
sockfd = (curl_socket_t)sockextr;
/* Extract the socket from the curl handle - we'll need it for waiting. */
res = curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockfd);
/* wait for the socket to become ready for sending */
if(!wait_on_socket(sockfd, 0, 60000L)) {
printf("Error: timeout.\n");
return 1;
}
puts("Sending request.");
/* Send the request. Real applications should check the iolen
* to see if all the request has been sent */
res = curl_easy_send(curl, request, strlen(request), &iolen);
if(CURLE_OK != res) {
if(res != CURLE_OK) {
printf("Error: %s\n", curl_easy_strerror(res));
return 1;
}
puts("Reading response.");
/* read the response */
printf("Sending request.\n");
do {
/* Warning: This example program may loop indefinitely.
* A production-quality program must define a timeout and exit this loop
* as soon as the timeout has expired. */
size_t nsent;
do {
nsent = 0;
res = curl_easy_send(curl, request + nsent_total,
request_len - nsent_total, &nsent);
nsent_total += nsent;
if(res == CURLE_AGAIN && !wait_on_socket(sockfd, 0, 60000L)) {
printf("Error: timeout.\n");
return 1;
}
} while(res == CURLE_AGAIN);
if(res != CURLE_OK) {
printf("Error: %s\n", curl_easy_strerror(res));
return 1;
}
printf("Sent %" CURL_FORMAT_CURL_OFF_T " bytes.\n",
(curl_off_t)nsent);
} while(nsent_total < request_len);
printf("Reading response.\n");
for(;;) {
/* Warning: This example program may loop indefinitely (see above). */
char buf[1024];
size_t nread;
do {
nread = 0;
res = curl_easy_recv(curl, buf, sizeof(buf), &nread);
wait_on_socket(sockfd, 1, 60000L);
res = curl_easy_recv(curl, buf, 1024, &iolen);
if(res == CURLE_AGAIN && !wait_on_socket(sockfd, 1, 60000L)) {
printf("Error: timeout.\n");
return 1;
}
} while(res == CURLE_AGAIN);
if(CURLE_OK != res)
if(res != CURLE_OK) {
printf("Error: %s\n", curl_easy_strerror(res));
break;
}
nread = (curl_off_t)iolen;
if(nread == 0) {
/* end of the response */
break;
}
printf("Received %" CURL_FORMAT_CURL_OFF_T " bytes.\n", nread);
printf("Received %" CURL_FORMAT_CURL_OFF_T " bytes.\n",
(curl_off_t)nread);
}
/* always cleanup */