Ребят, смешной для 21 века вопрос, но вот смущает он меня своей несуразностью для платформы, которой без малого 18 лет!
Итак, "закат солнца вручную" или "пишем сами http клиента". Ну а почему бы и нет?
Как многие знают, http весьма бестолков в плане проектирования, поэтому при получении ресурса может быть такая несуразица:
Текстовый заголовок (ответ сервера):
HTTP/1.1 200 OK
Content-Type: image/jpeg
...а за ним —
бинарные данные картинки! Т.е. в одном протоколе и строки, и "тупые байты".
Казалось бы, чего проще? Нам нужен сетевой класс, который может ReadLine(для заголовка) и одновременно — просто Read, выдавая элементарный byte[]!
КАК БЫ НЕ ТАК!
С классом Socket мелкомягкие нас прокатили — сделали тупой мэппинг юниксового сокета и на этом всё, там есть только Read.
Быть может, нам поможет NetworkStream? Да нет, такая же тупая проекция сокета с тем же бесполезным Read, только теперь в виде Потока.
Но ведь есть ещё StreamReader! И там даже есть ReadLine! Да, но по какой-то совершенно непонятной причине StreamReader был унаследован от TextReader и который вообще никогда не слышал про бинарные данные — он имеет метод Read, да только читает он не byte[], а char[]! (что очевидно, не одно и то же). Более того, на странице MSDN красный баннер прям так и предупреждает:
When you compile a set of characters with a particular cultural setting and retrieve those same characters with a different cultural setting, the characters might not be interpretable, and could cause an exception to be thrown.
Другими словами, "мы вам напроектировали кучу говна, а как вы будете это использовать — уже не наше дело". К пугвицам действительно претензий нет — ГДЕ У ПАЛЬТО РУКАВ?!
Ладно, но может есть счастье не в текстовых, а бинарных потоках? И действительно, забрезжила надежда в виде BinaryReader.ReadString, да вот только это не обычная строка "до перевода строки", а паскакаль-стайл строки с длиной в первом байте! Да ну жёваный крот...
Чуете проблему? Да-да, нам предлагают РУКАМИ читать куски данных через Socket.Read, искать там \r\n, выдавать строку, а когда коду понадобятся бинарные данные, мы должны
всё из того же буфера отдать byte[].
Что-то мне говорит, что в 21 веке уже не должно было быть таких проблем, как чтение строк из сокета! Идиотизм дотнета или я что-то пропустил за эти 18 лет??
PS
Я в курсе и про бесполезный TCPClient, и про WebClient (который неожиданным образом "устарел"), и про HttpClient... но опыт работы с этими ушлёпищами таков, что это танцы на костылях с коньками на концах. Это всё так же бестолково спроектированные и неуклюжие классы, где ты ничего не контролируешь. Да и не в них вопрос — тут глобальнее проблема: мы НЕ ДОЛЖНЫ зависеть от "устаревающих фантазий" MS в виде WebClient, а должны уметь писать сами ЛЮБОЙ протокол! Да-да, на тех самых Read[Line] — "полный контроль" и всё такое. Увы, не в этой жизни, видимо.
Итак, братья-апачи, есть какое-то адекватное решение проблеме из 1991 года? (год внедрения http)
Можно даже 3rd party library (как крайний вариант), но проверенная лично.