Получение данных на сервере? |
Здравствуйте, гость ( Вход | Регистрация )
Получение данных на сервере? |
V7T |
21.10.2011, 16:08
Сообщение
#1
|
Новичок Группа: Новичок Сообщений: 5 Регистрация: 11.10.2011 Пользователь №: 2939 Спасибо сказали: 0 раз(а) Репутация: 0 |
Здравствуйте, пишу клиент/серверное приложение, я использую FortuneClient и ThreadedFortuneServer из SDK QT.
Все бы ничего, но ни как не могу понять (это первое мое приложение в QT и собственно в линуксе), принцип получения данных на сервере. В самих примерах все достаточно просто, но там данные отправляются клиенту, который их принимает, перед этим отправив запрос. Собственно вот часть кода клиента: часть кода сервера:
В коде сервера явно не все впорядке (возможно и клиенте) , и Вас уважаемые гуру наверно . Правильно ли данные отправляются? Может стоит создать connect(сокет,сигнал(readyRead()),...,slot(..)), впринципе, что я только не делал, все одно - ничего)). Не первый день пытаюсь разобраться, окончательно запутался. Подскажите, пожалуйста. |
|
|
silver47 |
22.10.2011, 6:52
Сообщение
#2
|
Активный участник Группа: Участник Сообщений: 356 Регистрация: 1.4.2010 Пользователь №: 1584 Спасибо сказали: 40 раз(а) Репутация: 6 |
ThreadedFortuneServer устроен таким образом, что при новом соединении создается новый поток, а в нем, в свою очеред создается новый сокет. В сокет вываливается некая фраза, затем сокет на серверной стороне завершается и поток прибивается.
Обычно же, работа клиент-серверного ПО выглядит так: - клиент подключается к серверу - создается новый поток - создается сокет - клиент отправляет запрос - сервер принимет запрос (сигнал ReadyRead() сокета) - сервер отвечает клиенту - клиент принимает ответ (сигнал ReadyRead() сокета клиента) - клиент отключается - уничтожается сокет - уничтожается поток (сигнал finished() и слот DeleteLater() потока) P.S. где-то уже не так давно выкладывал я для кого-то пример. Нашел. В примере создается сервер, который вываливает в qDebug все что получает. При дисконекте клиента, сокет и поток удаляются Сообщение отредактировал silver47 - 22.10.2011, 7:02
Прикрепленные файлы
|
|
|
V7T |
23.10.2011, 13:39
Сообщение
#3
|
Новичок Группа: Новичок Сообщений: 5 Регистрация: 11.10.2011 Пользователь №: 2939 Спасибо сказали: 0 раз(а) Репутация: 0 |
Silver, спасибо за отзыв.
Я в принципе сам не много разобрался с получением данных на сервере, но пока без многопоточной реализации. Решил ее пока не трогать. Теперь появилась другая проблема, я написал небольшой класс для клиента, вызываю его в Main и все работает на ура (скриншот отправляется и принимается на сервере), но стоит в классе, который работает с формой (MainWindow.cpp) загнать тот же код, что и в Main, в обработчик события кнопки, как ни какой отправки не наблюдается, но соединение происходит и сервер его отлавливает (если в дебагер вывести содержимое сокета, то будет по нулям). Еще заметил, что если в Main несколько раз запустить один и тот же кусок кода, то первое соединение работает, а последующие нет (соединение происходит, но ни чего не отправляется). Причем, если через консоль запустить несколько экземпляров программы, то все работает, т.е. сервер не причем Вот привожу код клиента:
Код сервера
Что не так, подскажите |
|
|
silver47 |
24.10.2011, 9:55
Сообщение
#4
|
Активный участник Группа: Участник Сообщений: 356 Регистрация: 1.4.2010 Пользователь №: 1584 Спасибо сказали: 40 раз(а) Репутация: 6 |
А класс SendImage обязательно должен быть таким запутанным. Может просто послать эту картинку и всего делов?
Кроме того, насколько мне известно, кажется, что, оператор << перегружен для QImage. Если это так, то в этом шаманстве: нет смысла. Достаточно напрямую записать в поток и все:
Пы.Сы. А Вы уверенны, что картинка будет точно размером меньше 65килобайт? Сообщение отредактировал silver47 - 24.10.2011, 10:12 |
|
|
Гость_AntonT_* |
24.10.2011, 14:05
Сообщение
#5
|
Гости |
|
|
|
silver47 |
24.10.2011, 16:23
Сообщение
#6
|
Активный участник Группа: Участник Сообщений: 356 Регистрация: 1.4.2010 Пользователь №: 1584 Спасибо сказали: 40 раз(а) Репутация: 6 |
Цитата извиняюсь что влезаю со своим вопросом, а можно чуть по подробней ? Сообщение передается блоками данных. До того как сервер начнет что-либо читать из сокета, он должен знать точно размер блока, который читает. Для этого, в самом начале блока данных передается размер этого блока. За это отвечает вот это: . В данном случае размер блока не сможет превышать размер двухбайтового беззнакового целого, т.е. 65535 байт.
Сообщение отредактировал silver47 - 24.10.2011, 16:23 |
|
|
V7T |
25.10.2011, 0:13
Сообщение
#7
|
Новичок Группа: Новичок Сообщений: 5 Регистрация: 11.10.2011 Пользователь №: 2939 Спасибо сказали: 0 раз(а) Репутация: 0 |
А класс SendImage обязательно должен быть таким запутанным. Может просто послать эту картинку и всего делов? Пы.Сы. А Вы уверенны, что картинка будет точно размером меньше 65килобайт? ...хм, например, в дебагер размер Image вывожу, получаю около 200000 (размер байтового массива QByteArray), т.е., не хочу сморозить глупость, но как я понимаю это 200000 байт, следовательно изображение занимает около 200 кбайт. На сервере я спокойно их получаю. Получается, что все сообщение, в данном случае, разобьется на 4 блока. ...кстати да, убрал полностью класс SendImage, решил не заморачиваться с ним. Что касается прямого запихивания QImage в QDataStream, out<<image (альтернатива out<<(&out,&image) как то так, ) запихивается на ура, но на сервере QDataStream взяв сокет не хочет выводить данные в image напрямую (ошибок не наблюдается), т.е. сокет не пустой (сколько отправлено, столько и пришло). все как в документации.
А теперь самое интересное, неоднократно натыкался в интернете, на одну особенность или может быть в силу таких же кривых рук. Если передавать изображение так:
т.е. сохранить изображение в массив байтовый в формате PNG, на сервере тоже принимать в PNG (image.loadFromData(Block,"PNG");, то все работает замечательно. Но стоит поменять формат загрузки/разгрузки в/из байтового массива, например JPG, BMP то при получении на сервере (in>>Block, image.loadFromData(Block,"...")) c последующей проверкой image.isNull() - постое, по нулям, хотя поток блоковый заполнен. В результате, если отправлять/принимать только в PNG, то сохранять придется тоже в PNG (image.save(..."PNG")), в другом формате не получается, следовательно изображение будет занимать 3 метра. А это не выгодно, хотя мне для учебы не принципиально. Решение есть, если я отправляю просто pixmap, перед этим загнанный в массив, на сервере потом могу сохранять в любом формате, при этом экономя место. |
|
|
silver47 |
25.10.2011, 5:04
Сообщение
#8
|
Активный участник Группа: Участник Сообщений: 356 Регистрация: 1.4.2010 Пользователь №: 1584 Спасибо сказали: 40 раз(а) Репутация: 6 |
Получается, что все сообщение, в данном случае, разобьется на 4 блока. Никто за Вас ничего разбивать не будет. Для проверки просто выведите значение block.size() Что касается прямого запихивания QImage в QDataStream, Начните с малого. Передайте какие-нибудь числа, потом строки, потом байтовый масив произвольной длинны. Как только получиться передавать байтовый массив произвольной длины - Вы станете ближе к решению Вашей задачи. Сообщение отредактировал silver47 - 25.10.2011, 7:16 |
|
|
Текстовая версия | Сейчас: 7.11.2024, 5:48 |