В вашем коде довольно много проблем.
Сначала вы устанавливаете сокет в неблокирующее состояние. Я не понимаю, зачем ты это делаешь. Функция подключения имеет внутреннее время ожидания и поэтому не будет блокироваться.
Другая проблема вашего кода заключается в том, что первый оператор if пропустит блок инструкций, если соединение сразу установится! Что может случиться.
Вы, очевидно, хотите сначала отправить сообщение HEAD. Нет никакой необходимости делать этот блок неблокирующим, если вы не ожидаете, что удаленный сервер или сеть будут работать очень медленно, и вам не нужно время для этого. В этом случае выбор с неблокирующим сокетом будет иметь смысл.
После того, как вы отправите сообщение HEAD, вы ожидаете получить в ответ некоторые данные, которые вы собираете с помощью функции recv. Помните, что этот вызов функции может вернуться до получения всех отправленных данных. Вам нужен независимый способ определить, что все отправленные данные были получены. Будет ли сервер закрывать соединение? Это будет обнаружено функцией recv, возвращающей 0.
Таким образом, recv должен быть заключен в цикл, в который вы добавляете полученные данные в некоторый буфер или файл и завершаете работу, когда recv возвращает 0. Используйте неблокирующий сокет, если вы хотите добавить тайм-аут в эту операцию recv, которая может действительно блок.
Но сначала попробуйте без тайм-аутов, чтобы убедиться, что он работает на полной скорости без блокировки в качестве текущей версии.
Я подозреваю, что первоначальное соединение медленное из-за разрешения имен и IP-адресов, и ускоряется при последующих вызовах, потому что данные кэшируются.