Куда теряются пакеты ? QTcpServer QTcpClient, блокирующие сокеты |
Здравствуйте, гость ( Вход | Регистрация )
Куда теряются пакеты ? QTcpServer QTcpClient, блокирующие сокеты |
kwisp |
22.7.2009, 7:56
Сообщение
#21
|
астарожна ынтжинэр Группа: Участник Сообщений: 1404 Регистрация: 26.11.2008 Из: ТаганрогРодинаЧехова Пользователь №: 435 Спасибо сказали: 113 раз(а) Репутация: 23 |
|
|
|
ViGOur |
22.7.2009, 9:25
Сообщение
#22
|
Мастер Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: 40 |
а узких мест по склейке пакеов я не вижу. Я проверяю пакеты на целостность и жду ) Не вижу траблы. pirks, ты не исправим.Судя по всему ты совсем недавно начал изучать сокеты, да и по стилю программирования С\С++ также недолго изучаешь, пол года максимум год. Или это какой-то непонятный стеб! Тебе уже все описали, разжевали, только вот код не написали, а ты все гнешь свою линию! Ладно был бы прав и были бы железные теоретические или практические аргументы, а вот нет, обычное пустозвонство... С такой позицией как у тебя, тебе никто не будет писать код, так как он простой и видно, что ты просто не хочешь думать... так значит у тебя всё работает!!! поздравляю.
|
|
|
kuzulis |
22.7.2009, 14:52
Сообщение
#23
|
Активный участник Группа: Участник Сообщений: 393 Регистрация: 29.6.2009 Пользователь №: 862 Спасибо сказали: 36 раз(а) Репутация: 7 |
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 иначе возвращаем все прочитанные ранее данные (при этом можно не возвращать их) кароч идея дкмаю ясна... при таком подходе ничо теряться не будет и такой подход можно использовать - поставив на ожидание чтение из сокета (это в случае если мы не знаем когда данные придут.. ведь не обязательно сразу после коннекта они будут приходить ) |
|
|
pirks |
24.7.2009, 18:42
Сообщение
#24
|
Студент Группа: Участник Сообщений: 21 Регистрация: 5.7.2009 Пользователь №: 876 Спасибо сказали: 1 раз(а) Репутация: 0 |
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 байта. При таком подходе данные в буфере не затираются вновь прибывшими пакетами ? |
|
|
SABROG |
24.7.2009, 19:47
Сообщение
#25
|
Профессионал Группа: Участник Сообщений: 1207 Регистрация: 8.12.2008 Из: Russia, Moscow Пользователь №: 446 Спасибо сказали: 229 раз(а) Репутация: 34 |
При таком подходе данные в буфере не затираются вновь прибывшими пакетами ? если readAll() не вызывал, то данные будут "валяться" в буффере до тех пор, пока их не заберешь, а новые добавляться к существующим. Если надо просто взглянуть, что находится в буффере без его очистки, то можно использовать метод peek(). Сообщение отредактировал SABROG - 24.7.2009, 19:48 |
|
|
pirks |
25.7.2009, 11:25
Сообщение
#26
|
Студент Группа: Участник Сообщений: 21 Регистрация: 5.7.2009 Пользователь №: 876 Спасибо сказали: 1 раз(а) Репутация: 0 |
Вот интересно - если мой код находиться в слоте readyRead () и используются неблокирующие сокеты. то всё отлично работает . а если ТОТ ЖЕ самый код поместить в поток в цыкле типа
Ведь получается что цыкл иметирует слот readyRead () , следовательно принципиальной разници нет. Или я не прав ? |
|
|
kuzulis |
25.7.2009, 17:36
Сообщение
#27
|
Активный участник Группа: Участник Сообщений: 393 Регистрация: 29.6.2009 Пользователь №: 862 Спасибо сказали: 36 раз(а) Репутация: 7 |
Цитата В принципе ясно. Только в пункте 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, 21:23
Сообщение
#28
|
Студент Группа: Участник Сообщений: 21 Регистрация: 5.7.2009 Пользователь №: 876 Спасибо сказали: 1 раз(а) Репутация: 0 |
Цитата В принципе ясно. Только в пункте 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
|
|
|
pirks |
29.8.2009, 18:42
Сообщение
#29
|
Студент Группа: Участник Сообщений: 21 Регистрация: 5.7.2009 Пользователь №: 876 Спасибо сказали: 1 раз(а) Репутация: 0 |
Я понял в чём таки трабла !!!
Мой алгоритм (и все его версии) ПРАВЕЛЬНЫЕ. Всё дело было в том что я создавал сокет в основном потоке, а потом передовал в поток его дескриптор. Видемо функции работы с сетью в QT не всегда рентабельны. Перенёс создание сокета в сам поток и всё отлично теперь работает. Благодарю всех за внимание, тему можно считать закрытой. |
|
|
Текстовая версия | Сейчас: 27.11.2024, 1:49 |