Обертывание libcurl с помощью std::streambuf для загрузки?

Я реализовал половину API std::streambuf для чтения (т. е. underflow() и xsgetn()) вокруг libcurl, чтобы к обычному istream можно было подключить такой streambuf и получать содержимое с HTTP- или FTP-серверов. Это прекрасно работает.

Теперь я хотел бы реализовать половину записи API (т. е. overflow() и xsputn()) для загрузки файлов на FTP-сервер, чтобы сделать что-то вроде:

ostream os( my_curl_streambuf );
curl_easy_setopt( my_curl_handle, CURLOPT_UPLOAD, 1L );
os << is->rdbuf(); // copy entire contents of istream "is" to ostream "os"

Проблема в том, что libcurl использует «вытягивающий» API через функцию обратного вызова чтения, установленную через CURLOPT_READFUNCTION, тогда как последняя строка кода выше — это «выталкивающий» способ сделать это.

Можно ли заставить это работать? То есть обернуть libcurl streambuf API как для чтения , так и для записи?


person Paul J. Lucas    schedule 28.12.2013    source источник
comment
Это можно сделать, но независимо от того, как вы это сделаете, вы увязнете в том факте, что сокеты асинхронны, а потоки синхронны, поэтому независимо от того, как вы это делаете, скорее всего, это не сработает. работать достаточно хорошо, чтобы оправдать работу.   -  person Jerry Coffin    schedule 28.12.2013
comment
Хотите уточнить часть «Это можно сделать»? Я буду тем, кто решит, стоит ли это того.   -  person Paul J. Lucas    schedule 28.12.2013
comment
Одной из возможных отправных точек может быть: codereview.stackexchange.com/q/14389/489.   -  person Jerry Coffin    schedule 28.12.2013
comment
Этот код предназначен только для чтения, что мой код уже делает (и делает это лучше, поскольку обрабатывает тайм-ауты). Я специально спросил о письме.   -  person Paul J. Lucas    schedule 28.12.2013
comment
Хм... Кажется, я припоминаю, что у него были write и writecallback (или что-то в этом роде), которые выглядели так, как будто они предназначались для письма. Если я не так запомнил (или неправильно прочитал), прошу прощения.   -  person Jerry Coffin    schedule 28.12.2013


Ответы (1)


Я недостаточно знаю об API libcurl, но я ожидаю, что он извлекает данные до тех пор, пока все данные не будут исчерпаны. Поскольку IOStreams имеет интерфейс push, который не будет легко сочетаться с интерфейсом pull, кажется, вам лучше всего реализовать поток, который буферизует весь вывод до его завершения, и в этот момент libcurl pull для легкодоступного буфера. Вы, вероятно, должны были бы sync() ничего не делать, а вместо этого предоставить пользовательскую функцию, скажем, send() в вашем потоке, которая является триггером для передачи управления libcurl, пока он не закончит свою работу.

Альтернативным подходом было бы использование потока для извлечения libcurl и другого потока для записи в поток и подачи битов, которые записываются в libcurl, когда он извлекает данные.

person Dietmar Kühl    schedule 28.12.2013