61 / 61 / 15
Регистрация: 18.05.2015
Сообщений: 322
|
|
1 | |
Никак не могу понять, как узнать, сколько байт читать из сокета30.03.2016, 17:41. Показов 3572. Ответов 6
Метки нет (Все метки)
Честно говоря, пишу не на C++, но вопрос этот может возникнуть в любом языке.
Вот, допустим, я пишу клиент к какому-то протоколу (не буду говорить, к какому, а то сразу посоветуют готовую библиотеку и обсуждение закончится), который коннектится по TCP, Отправляет какие-то данные и должен получить в ответ от сервера данные. При этом данные получаются в формате, похожем на XML и они не оканчиваются CRLF или вообще чем-то особенным, просто идет ">" в конце последнего тега, но, т.к. там есть вложенные теги, понятно, что ориентироваться на них нельзя. Я не знаю, сколько именно данных приходит, но должен получить их все (довольно логично). Можно ли как-то узнать, сколько там данных пришло в ответ? Самое лучшее, до чего я додумался - это в цикле читать с таймаутом по одному байту, но это получается очень неэффективно и в конце подвисает на таймаут (что логично). Все вопросы подобного рода связаны с сервер сайд (ощущение, что народ во всем мире только отправляет данные, а что приходит в ответ уже никто не смотрит).
0
|
30.03.2016, 17:41 | |
Ответы с готовыми решениями:
6
Не могу никак понять как делать Никак не могу понять как рассуждать в задачи Как узнать, сколько байт прочитано? НовичОк в Scilab - никак не могу понять как записать правильно формулы. Постоянно путаюсь в скобках |
Native x86
5451 / 3238 / 929
Регистрация: 13.02.2013
Сообщений: 10,296
|
|
30.03.2016, 17:44 | 2 |
Реализуйте простейший протокол приложения, который передает сначала размер пакета (первые четыре байта), а потом и сами данные. Этим вы заодно решите проблему склейки отправленных друг за другом пакетов.
0
|
61 / 61 / 15
Регистрация: 18.05.2015
Сообщений: 322
|
|
30.03.2016, 18:50 [ТС] | 3 |
Протокол уже реализован, в том-то и дело, что я не могу повлиять на имплементацию сервера, иначе я бы просто установил какую-нибудь управляющую последовательность, которая должна стоять в конце.
Протокол - XMPP, но вопрос не в нем конкретно, а как в принципе это делается.
0
|
322 / 170 / 24
Регистрация: 25.03.2012
Сообщений: 712
|
|
30.03.2016, 21:53 | 5 |
Сообщение было отмечено klopik как решение
Решение
Это вопросы обеих сторон ... это вопросы TCP.
В TCP нет "пакетов" - вы можете отправлять по 20 байт, а получать за одно чтение и 5 байт и 30.. TCP - это поток, труба, куда в один конец вливаются байты, а из другого они вытекают. Подавляющее большинство сетевых протоколов (HTTP, SIP, и др.) на уровне выше транспортного используют фиксированный разделитель сообщений. Обычно это "\n\n" - пустая строка. Иногда перед сообщением (чаще бинарным) следует его последующая длина в фиксированном числе байт (часто 2). Это другой способ, но реже употребляемый. В любом случае, поток TCP приходится читать побайтно. А чтобы это реально не делать, добавляется промежуточный уровень буферизации, когда читается в фиксированный буфер "сколько дадут" (это не предсказуемо!), а оттуда уже выгребается побайтно. Всё это замечательно описано в книгах Р.Стивенса. Или см. Сетевое программирование в Linux (там есть примеры кода).
2
|
61 / 61 / 15
Регистрация: 18.05.2015
Сообщений: 322
|
|
31.03.2016, 13:54 [ТС] | 6 |
Кажется, я придумал решение, во всяком случае, оно должно подходить для XMPP и других подобных протоколов.
Решение заключается в том, чтобы читать побайтно из сокета (как советуют выше) до возникновения ошибки либо до появления определенной конструкции в строке. Например, первый ответ от jabber-сервера по нормальному должен оканчиваться закрывающим тегом "</stream:features>", соответственно, мой код ожидает появления этого тега и, если он встретился, чтение заканчивается. Ну и при ошибке (таймаут) также происходит завершение цикла.
0
|
322 / 170 / 24
Регистрация: 25.03.2012
Сообщений: 712
|
|
31.03.2016, 17:14 | 7 |
Только для этого не нужно читать из сокета побайтно (очень уж накладно дёргать ОС за каждым байтом).
- Вы можете читать свои байты из промежуточного буфера достаточно большой длины ... скажем 1500 байт - а если указатель читаемого байта дощёл до конца буфера, то запрашивать чтение полной длины, те же 1500 байт - получите реально доступные в сокете данные ... 55 байт, например - переустановите указатель на начало буфера и снова дёргаете по одому байту...
0
|
31.03.2016, 17:14 | |
31.03.2016, 17:14 | |
Помогаю со студенческими работами здесь
7
Никак не могу понять Maple, никак не могу понять Не могу никак понять (новичек). никак не могу понять задачу Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |