Обрыв соединения QTcpSocket |
Здравствуйте, гость ( Вход | Регистрация )
Обрыв соединения QTcpSocket |
OrSOn |
16.2.2010, 14:47
Сообщение
#1
|
Студент Группа: Участник Сообщений: 46 Регистрация: 8.12.2009 Пользователь №: 1289 Спасибо сказали: 0 раз(а) Репутация: 0 |
Всем добрый день! Столкнулся с довольно неприятной проблемой при работе с сокетами... Суть проблемы в следующем:
Имеется сервер и клиент, для общения используют сокеты. В некий момент времени клиент рушится (ну или связь падает, не суть важно), при этом сервер пытается что-то писать в сокет, что приводит к ошибке. Чтобы избежать этого, пробовал ввести проверку
Так вот случаются ситуации, что проверка состояния проходит, а сразу после нее до начала проталкивания информации клиент падает и на tcpSocket->flush() снова вылетаю с ошибкой. Если кто сталкивался с подобным, подскажите, пожалуйста, как это можно обойти... Сообщение отредактировал OrSOn - 16.2.2010, 14:48 |
|
|
sploid |
16.2.2010, 17:29
Сообщение
#2
|
Студент Группа: Участник Сообщений: 51 Регистрация: 26.2.2008 Из: Москва Пользователь №: 106 Спасибо сказали: 10 раз(а) Репутация: 1 |
так в чем проблема? в том что сервер не знает записаны данные или нет?
|
|
|
SABROG |
16.2.2010, 20:28
Сообщение
#3
|
Профессионал Группа: Участник Сообщений: 1207 Регистрация: 8.12.2008 Из: Russia, Moscow Пользователь №: 446 Спасибо сказали: 229 раз(а) Репутация: 34 |
|
|
|
OrSOn |
17.2.2010, 10:07
Сообщение
#4
|
Студент Группа: Участник Сообщений: 46 Регистрация: 8.12.2009 Пользователь №: 1289 Спасибо сказали: 0 раз(а) Репутация: 0 |
Обработать ошибку нельзя - полностью прерывается дебаг и вылетаю, ошибка получается в том, что я пытаюсь записать информацию в сокет, который имеет состояние disconnected(), причем это состояние он получает в процессе выполнения команды записи, т.е. заранее это не отследить. Грубо говоря, получается такая ситуация:
1. Сокет подключен, начинается запись (запускается стандартная функция Qt) 2. Прямо во время записи рвется соединение 3. Половина функции прошла, а во второй оказывается, что соединения нет и вылетает ошибка... |
|
|
BRE |
17.2.2010, 10:15
Сообщение
#5
|
Профессионал Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: 44 |
Обработать ошибку нельзя - полностью прерывается дебаг и вылетаю, ошибка получается в том, что я пытаюсь записать информацию в сокет, который имеет состояние disconnected(), причем это состояние он получает в процессе выполнения команды записи, т.е. заранее это не отследить. Грубо говоря, получается такая ситуация: 1. Сокет подключен, начинается запись (запускается стандартная функция Qt) 2. Прямо во время записи рвется соединение 3. Половина функции прошла, а во второй оказывается, что соединения нет и вылетает ошибка... Покажи код, как ты это делаешь. Никаких вылетов быть не должно. |
|
|
OrSOn |
17.2.2010, 10:19
Сообщение
#6
|
Студент Группа: Участник Сообщений: 46 Регистрация: 8.12.2009 Пользователь №: 1289 Спасибо сказали: 0 раз(а) Репутация: 0 |
Вот, это "тот самый" кусок примера... Как видно, уже везде, где только можно, включена проверка на разрывы
Тем не менее, на строке while( tcpSocket->flush() ) вылетает ошибка, потому что разрыв умудряется произойти во время выполнения... З.Ы. чтобы не так нагромождено все было, вот изначальный код без проверок
Сообщение отредактировал OrSOn - 17.2.2010, 10:21 |
|
|
BRE |
17.2.2010, 10:25
Сообщение
#7
|
Профессионал Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: 44 |
Покажи как создается объект tcpSocket и какие сигналы обрабатываются.
Ты уверен, что этот объект не разрушается где-то еще (вижу там какой-то freeThread)? Все эти проверки не нужны, ошибка где-то в другом месте. У тебя течет память для буфера dataBlock, при любой ошибки - она не удаляется. Зачем цикл у flush? Сообщение отредактировал BRE - 17.2.2010, 10:27 |
|
|
OrSOn |
17.2.2010, 10:34
Сообщение
#8
|
Студент Группа: Участник Сообщений: 46 Регистрация: 8.12.2009 Пользователь №: 1289 Спасибо сказали: 0 раз(а) Репутация: 0 |
Значит по порядку...
Объект создается нормально, но в другом классе (раньше все работало, пока я не стал разбивать файлы на блоки, т.е. когда файл отсылал целиком, никаких ошибок не было). Суть в следующем: есть управляющий класс,в нем QTcpServer. Когда поступает запрос подключения, создается сокет, затем он добавляется в очередь. А далее из очереди сокеты передаются в заранее созданные потоки на обработку, после чего возвращаются обратно в очередь. Насчет не освобождается память - я в курсе, это не страшно в данном случае (ошибки от этого не возникнет), потом устраню, когда разберусь, где все рушится. Цикл сделан тоже неспроста... Раньше было без него, но столкнулся с некоторой проблемой - длинные файлы просто не передавались целиком, т.е. часть файла принималась с клиентской стороны, а потом сигналы readyRead() просто переставали приходить, т.е. каким-то образом остатки файла не проталкивались, хотя сервер и уходил дальше в eventLoop... Да и не в этом проблема, он рушится даже на первом вызове... Вот и не могу понять, почему при неизменном коде все работало при отправке файлов целиком и стало рушится при разбиении на блоки... И кстати, проверки, все же, нужны, но несколько для других целей - чтобы остановить выполнение функции после разрыва соединения, иначе будет путаница с данными, если этот сокет разорвался, а потоку дали другой на обработку... И новый сокет "завершит" действия, которые предназначались не ему. Сообщение отредактировал OrSOn - 17.2.2010, 10:36 |
|
|
BRE |
17.2.2010, 10:50
Сообщение
#9
|
Профессионал Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: 44 |
Класс TcpSocket данные кеширует сам и отправляет их блоками. Происходит это в цикле обработки событий.
Ты не показал код..., но мне кажется, что при разрыве соединения сам объект на который указывает tcpSocket разрушается (например в другом потоке), и ты пытаешься использовать уже разрушенный объект. Метод write возвращает размер реально записанных данных, не всегда все данные могут поместиться в буфер отправки TCP-стека (хотя Qt и кеширует их сам). Эту ситуацию так же нужно обрабатывать. |
|
|
OrSOn |
17.2.2010, 11:02
Сообщение
#10
|
Студент Группа: Участник Сообщений: 46 Регистрация: 8.12.2009 Пользователь №: 1289 Спасибо сказали: 0 раз(а) Репутация: 0 |
Увы, но удаления объекта не происходит. Я уже думал об этом, поэтому тупо закомментировал ВСЕ места, где происходит удаление - результата нет. А насчет обработки записи, flush() записывает максимально возможное количество информации (не дожидаясь возвращения в цикл обработки событий), поэтому помещение его в цикл (пока записывается) как раз и осуществляет эту обработку (я уже проверял на файлах по 1.36 гигабайта). И если соединение не рвать, тов се работает и передается отлично, ломается только при закрытии клиента.
З.Ы. как говорит ассистант, мы не можем использовать flush() для сокетов, у которых состояние не connected(), так что рушится оно неспроста... А вот как обойти - хз. З.З.Ы. код показать не могу, ибо там слишком много и все в разных классах... Но если конкретно создание сокета интересует, то вот оно:
Это содержимое слота, который обрабатывает сигнал newConnection() Сообщение отредактировал OrSOn - 17.2.2010, 11:05 |
|
|
Текстовая версия | Сейчас: 30.11.2024, 23:03 |