Я работаю над программой для личного пользования, которая периодически очищает несколько веб-страниц. Один из них требует использования SSL, а его основной URL фактически является балансировщиком нагрузки, который каждый раз перенаправляет на другой домен из списка нескольких (не уверен, что это актуально). Я совершенно новичок в libcurl и SSL, в частности, поэтому я могу упустить что-то очевидное, но я так не думаю.
Некоторое время программа работает нормально (пока что никогда не дольше, чем час), но как только она впервые получает ошибку соединения SSL, она будет каждый раз выдавать одну и ту же ошибку. Это всегда разное количество времени и разное количество успешных запросов, прежде чем он начнет давать сбои.
Буфер ошибок всегда содержит следующее: schannel: next InitializeSecurityContext failed: SEC_E_ILLEGAL_MESSAGE (0x80090326) - This error usually occurs when a fatal SSL/TLS alert is received (e.g. handshake failed). More detail may be available in the Windows System event log.
Там нет ничего полезного в eventvwr
, Поиски по этому коду ошибки возвращают результаты о проблемах с самозаверяющими сертификатами в более ранних версиях Windows Server, но мало что еще. Я не контролирую сервер, к которому подключаюсь, но сомневаюсь, что это Windows-бокс.
У меня закончились идеи, поэтому я просто собираюсь рассказать о любых деталях, которые могут иметь отношение к делу. Я действительно не могу опубликовать какой-либо реальный исходный код, потому что я абстрагировал все вызовы curl в нескольких классах, поэтому мне пришлось бы вставить много шаблонного кода, чтобы другие могли его понять. С помощью отладчика Visual Studio я подтвердил, что это то, к чему сводятся реальные вызовы.
Я инициализирую libcurl в главном потоке перед созданием других, например так: curl_global_init(CURL_GLOBAL_WIN32 | CURL_GLOBAL_SSL);
Затем я создаю и инициализирую фактическую ручку curl во втором потоке, и только в этом потоке, вот так:
m_handle = curl_easy_init();
curl_easy_setopt(m_handle, CURLOPT_WRITEDATA, this);
curl_easy_setopt(m_handle, CURLOPT_WRITEFUNCTION, write);
curl_easy_setopt(m_handle, CURLOPT_DEBUGDATA, this);
curl_easy_setopt(m_handle, CURLOPT_DEBUGFUNCTION, debug);
curl_easy_setopt(m_handle, CURLOPT_VERBOSE, 1);
curl_easy_setopt(m_handle, CURLOPT_ERRORBUFFER, &m_errormsg[0]);
curl_easy_setopt(m_handle, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(m_handle, CURLOPT_COOKIEFILE, "");
Я экспериментировал с настройкой обоих CURLOPT_SSL_VERIFYHOST
а также CURLOPT_SSL_VERIFYPEER
до 0, но это не помогло.
Я построил libcurl из curl-7.43.0.tar.gz
с nmake /f Makefile.vc mode=static VC=12 ENABLE_WINSSL=yes ENABLE_SSPI=yes MACHINE=x64 DEBUG=yes
на Visual Studio 2013.
Что здесь происходит и как я могу это исправить?
Я предполагаю, что вы используете один дескриптор CURL для всех ваших запросов (поскольку вы говорите: «Я создаю и инициализирую»). фактический дескриптор curl «). Решение, скорее всего, создаст один дескриптор CURL для каждого запроса, выполненного с помощью curl_easy_perform (), а затем сразу же curl_easy_cleanup ().
То, что вы видите, вероятно, вызвано отключением SSL-соединения сервером. Но ваш дескриптор CURL, скорее всего, сохраняет свое состояние как есть (то есть с завершенным рукопожатием), что больше не подходит.
CURL *handle = curl_easy_init();
char url[] = "https://google.com";
curl_easy_setopt(handle, CURLOPT_URL, url);
curl_easy_perform(handle);
должно сработать…