Здравствуйте, гость ( Вход | Регистрация )
pirks | Дата 29.8.2009, 18:42 |
Я понял в чём таки трабла !!! Мой алгоритм (и все его версии) ПРАВЕЛЬНЫЕ. Всё дело было в том что я создавал сокет в основном потоке, а потом передовал в поток его дескриптор. Видемо функции работы с сетью в QT не всегда рентабельны. Перенёс создание сокета в сам поток и всё отлично теперь работает. Благодарю всех за внимание, тему можно считать закрытой. |
|
pirks | Дата 25.7.2009, 21:23 |
Цитата В принципе ясно. Только в пункте 4 - если не читать любое доступное колличество байт, а при несовпадении с неким минимально допустимым размером куска данных, сделать waitForReadyRead и затем считать кусок большего размера. ну да! я это привел просто чтобы показать сам принцип.. а так конечно, необходимо контролировать несовпадение и т.п. .. это по умолчанию и так понятно ! ![]() Цитата К примеру мне пришло 3 байта, а я хочу считать за раз 4, т.к. у меня размер пакета 4 байта. При таком подходе данные в буфере не затираются вновь прибывшими пакетами ? если пришло 3 байта, то bytesAvailable() покажет что пришло в данный момент 3 байта.. и за раз нужно читать 3 байта... а потом уже в следующий раз (если прочитали не весь пакет) - опять сделать waitForReadyRead() и когда он отработает (т.е когда придет снова хотя-бы 1 байт) - сделать опять то bytesAvailable() и считать из буфера уже например 1 байт, чтобы получился весь пакет! далее... после операции чтения те данные которые уже прочитали - больше не прочитаются.. т.к. типа они "затрутся", так что волноваться не о чем ![]() Цитата Вот интересно - если мой код находиться в слоте readyRead () и используются неблокирующие сокеты. то всё отлично работает ![]() неправда! не будет отлично работать т.к. readyRead () срабатывает только если приходит хотя-бы один байт! И если например мы ожидаем пакет в 1000 байт, и срабатывает readyRead () - то это не значит что в буфер пришли все 1000 байт.. это значит что пришло >=1 байта! Поэтому если мы выполним операцию чтения read(1000) - то не факт что мы прочитаем 1000 байт за раз! И в этом случае нужно ловить сигнал readyRead() lдо тех пор, пока мы не прочитаем ВСЕ 1000 байт (по частям)! И я все-таки предпочитаю принцип который изложил выше, т.к. если постоянно полагаться на radyRead() - то можно где - нить накосячить... Хотя.. нужно смотреть по обстакановке ИМХО ![]() Я проверяю на наличие нужного мне колличества байт. И при отсутсвии нужного мне колличества байт жду .. newRead
|
|
kuzulis | Дата 25.7.2009, 17:36 |
Цитата В принципе ясно. Только в пункте 4 - если не читать любое доступное колличество байт, а при несовпадении с неким минимально допустимым размером куска данных, сделать waitForReadyRead и затем считать кусок большего размера. ну да! я это привел просто чтобы показать сам принцип.. а так конечно, необходимо контролировать несовпадение и т.п. .. это по умолчанию и так понятно ! ![]() Цитата К примеру мне пришло 3 байта, а я хочу считать за раз 4, т.к. у меня размер пакета 4 байта. При таком подходе данные в буфере не затираются вновь прибывшими пакетами ? если пришло 3 байта, то bytesAvailable() покажет что пришло в данный момент 3 байта.. и за раз нужно читать 3 байта... а потом уже в следующий раз (если прочитали не весь пакет) - опять сделать waitForReadyRead() и когда он отработает (т.е когда придет снова хотя-бы 1 байт) - сделать опять то bytesAvailable() и считать из буфера уже например 1 байт, чтобы получился весь пакет! далее... после операции чтения те данные которые уже прочитали - больше не прочитаются.. т.к. типа они "затрутся", так что волноваться не о чем ![]() Цитата Вот интересно - если мой код находиться в слоте readyRead () и используются неблокирующие сокеты. то всё отлично работает ![]() неправда! не будет отлично работать т.к. readyRead () срабатывает только если приходит хотя-бы один байт! И если например мы ожидаем пакет в 1000 байт, и срабатывает readyRead () - то это не значит что в буфер пришли все 1000 байт.. это значит что пришло >=1 байта! Поэтому если мы выполним операцию чтения read(1000) - то не факт что мы прочитаем 1000 байт за раз! И в этом случае нужно ловить сигнал readyRead() lдо тех пор, пока мы не прочитаем ВСЕ 1000 байт (по частям)! И я все-таки предпочитаю принцип который изложил выше, т.к. если постоянно полагаться на radyRead() - то можно где - нить накосячить... Хотя.. нужно смотреть по обстакановке ИМХО ![]() |
|
pirks | Дата 25.7.2009, 11:25 |
Вот интересно - если мой код находиться в слоте readyRead () и используются неблокирующие сокеты. то всё отлично работает ![]()
Ведь получается что цыкл иметирует слот readyRead () , следовательно принципиальной разници нет. Или я не прав ? ![]() |
|
SABROG | Дата 24.7.2009, 19:47 |
При таком подходе данные в буфере не затираются вновь прибывшими пакетами ? если readAll() не вызывал, то данные будут "валяться" в буффере до тех пор, пока их не заберешь, а новые добавляться к существующим. Если надо просто взглянуть, что находится в буффере без его очистки, то можно использовать метод peek(). |
|
pirks | Дата 24.7.2009, 18:42 |
2 pirks, смотри какой принцип чтения из сокета использую Я : 1. делаем waitForReadyRead(таимаут ожидания прихода пакета); // ожидаем прихода хотябы одного байта в сокет 2. если ф-я в п.1 вернула true - то к П.3. иначе говорим что таймаут ожидания байтов 3. делаем bytesAvailable() //получаем количество пришедших в сокет байт 4. если >0 то читаем это количество байт иначе говорим что ошибка 4.1 приплюсовываем прочитанные данные к тем, которые прочитали на предыдущем шаге.. и если их длина буит = длине ожидаемого пакета то возвращаем пакет , иначе к п.5. 5. делаем waitForReadyRead(таймаут ожидания прихода следующего символа) //если пакет прочитали не весь -здесь можно ставить 1-5 мс (т.е мы уверены, что следующий пакет придет только через 1-5 мс и мы не прочитаем кусок из следующего пакета) 6. если в п.5. вернула true то переходим к п.3 иначе возвращаем все прочитанные ранее данные (при этом можно не возвращать их) кароч идея дкмаю ясна... при таком подходе ничо теряться не будет и такой подход можно использовать - поставив на ожидание чтение из сокета (это в случае если мы не знаем когда данные придут.. ведь не обязательно сразу после коннекта они будут приходить ) ![]() В принципе ясно. Только в пункте 4 - если не читать любое доступное колличество байт, а при несовпадении с неким минимально допустимым размером куска данных, сделать waitForReadyRead и затем считать кусок большего размера. К примеру мне пришло 3 байта, а я хочу считать за раз 4, т.к. у меня размер пакета 4 байта. При таком подходе данные в буфере не затираются вновь прибывшими пакетами ? |
|
kuzulis | Дата 22.7.2009, 14:52 |
2 pirks, смотри какой принцип чтения из сокета использую Я : 1. делаем waitForReadyRead(таимаут ожидания прихода пакета); // ожидаем прихода хотябы одного байта в сокет 2. если ф-я в п.1 вернула true - то к П.3. иначе говорим что таймаут ожидания байтов 3. делаем bytesAvailable() //получаем количество пришедших в сокет байт 4. если >0 то читаем это количество байт иначе говорим что ошибка 4.1 приплюсовываем прочитанные данные к тем, которые прочитали на предыдущем шаге.. и если их длина буит = длине ожидаемого пакета то возвращаем пакет , иначе к п.5. 5. делаем waitForReadyRead(таймаут ожидания прихода следующего символа) //если пакет прочитали не весь -здесь можно ставить 1-5 мс (т.е мы уверены, что следующий пакет придет только через 1-5 мс и мы не прочитаем кусок из следующего пакета) 6. если в п.5. вернула true то переходим к п.3 иначе возвращаем все прочитанные ранее данные (при этом можно не возвращать их) кароч идея дкмаю ясна... при таком подходе ничо теряться не будет и такой подход можно использовать - поставив на ожидание чтение из сокета (это в случае если мы не знаем когда данные придут.. ведь не обязательно сразу после коннекта они будут приходить ) ![]() |
|
ViGOur | Дата 22.7.2009, 9:25 |
а узких мест по склейке пакеов я не вижу. Я проверяю пакеты на целостность и жду ) Не вижу траблы. pirks, ты не исправим.Судя по всему ты совсем недавно начал изучать сокеты, да и по стилю программирования С\С++ также недолго изучаешь, пол года максимум год. Или это какой-то непонятный стеб! Тебе уже все описали, разжевали, только вот код не написали, а ты все гнешь свою линию! Ладно был бы прав и были бы железные теоретические или практические аргументы, а вот нет, обычное пустозвонство... С такой позицией как у тебя, тебе никто не будет писать код, так как он простой и видно, что ты просто не хочешь думать... так значит у тебя всё работает!!! поздравляю. ![]() ![]() |
|
kwisp | Дата 22.7.2009, 7:56 |
а узких мест по склейке пакеов я не вижу. Я проверяю пакеты на целостность и жду ) Не вижу траблы. так значит у тебя всё работает!!! поздравляю. ![]() П.С. чего тогда вопросы задавать? надо наслаждаться кропотливым жужжанием своей программы, раз "траблов" нет ![]() |
|
pirks | Дата 22.7.2009, 6:14 |
Сокеты это сокеты беркли ) их я знаю. Это давным давно придуманная технология. Всё остальное эт обёртки. Они нужны только для упрощения и кросплатформенности. Если бы это было так, то не нужно было бы виндовый сокеты (WSA) скрещивать с BSD cокетами (беркли) с макросами ifdef UNIX и прочими. Хоть сокеты Windows и разработанный на основе сокетов Беркли, но частично. Чтобы убедиться в этом глянь кроссплатформенные реализации Boost (asio), ACE, POCO, Qt ...Ты споришь не там где нужно, лучше прочти мой последний ответ тебе, я описал в чем проблемы. хм, сокеты виндовс..... да это в принципе они ничего сами не писали, взяли бсдишные и закрыли исходники! первая версия это один в один, за исключением инициализации, самого типа дескриптора да названия парочки структур ))) Мелкософт в принципе не способен сам придумать ничего нормального. всё покупают да переделывают. >>pirks, очень сложно помочь человеку, если он не слушает советы. Перечитай сообщения ViGOur(а), найди у себя в коде указанные узкие места и попробуй их переделать - >>возможно, и поможет! ![]() я переделывал по разному, а узких мест по склейке пакеов я не вижу. Я проверяю пакеты на целостность и жду ) Не вижу траблы. |
|
Просмотр темы полностью (откроется в новом окне) | |
![]() |
Текстовая версия | Сейчас: 18.2.2025, 0:33 |