Название: Работа с QTcpSocket Отправлено: Ruzzz от Ноябрь 02, 2009, 19:12 Как начинающий Qt'шник решил разобраться с QTcpSocket и привести в порядок мысли. Первым делом изучил класс QTcpSocket в Help'е. Затем изучил примеры Fortune Server и Threaded Fortune Server. Ну и решил сделать некий график для себя. Делюсь - скачать (http://narod.ru/disk/14702379000/Work%20with%20QTcpSocket.7z.html) файл для XMind или в виде картинки:
(http://pic.ipicture.ru/uploads/091102/8CLPxFDDkf.png) Немного комментариев и за одно вопросов. Работая с QTcpServer у нас есть две возможности обрабатывать входящие соединения:
После выполнения listen, как я понимаю где-то в недрах QtNetwork выполняется QTcpServer::waitForNewConnection, из которой идет вызов QTcpServerPrivate::readNotification, в теле этой функции я и нашел такие вызовы: Код: QTcpServer::incomingConnection(int socketDescriptor); То есть здесь и происходит вызов incomingConnection, а затем посылка сигнала newConnection. Что говорит нам, что эти способы не взаимоисключающие, и мы можем использовать их оба для своих нужд, мало ли. Теперь хотел бы рассмотреть код QTcpServer::incomingConnection(int socketDescriptor): Код: QTcpSocket *socket = new QTcpSocket(this); Динамически в куче создается новый экземпляр сокета, связывается с входящим подключением и сохраняется в списке. Важно что QTcpSocket создается в основном потоке! Поэтому если мы не переопределяем incomingConnection и хотим использовать сокет не в главном потоке, то не забываем делать: setParent(0) и потом QObject->moveToThread() и не забываем что теперь за удаление отвечаем мы. Интересно что добавляемый в список (в третьей строке) сокет, удаляется оттуда QTcpSocket *QTcpServer::nextPendingConnection(). Теперь рассмотрим способ с сигналом newConnection. Создаем наследник QTcpServer, например myTcpServer. В его конструкторе связываем сигнал с нашим слотом строкой connect(myTcpServer, SIGNAL(newConnection()), myTcpServer, SLOT(connectionProcess()));. Далее в слоте имеет примерно такой код: Код: QTcpSocket *clientConnection = myTcpServer->nextPendingConnection(); Первая строка извлекает раннее сохраненный в списке объект QTcpSocket. Важно, что он сохранялся в incomingConnection, поэтому если мы ее будем переопределять, то использовать nextPendingConnection нельзя. Далее вторая строка, говорит что при дисконнекте мы поставим объект сокета в очередь на удаление. Если мы создали сокет динамически где-то раньше, то после того как сокет соединился, это верный способ для его удаления. В конце мы даем команду оборвать соединение. Далее способ с переопределением incomingConnection В примере Threaded Fortune Server в теле функции создается новый поток, и уже в нем идет работа с сокетом, отвечающим за соединение. Но как я понимаю никто не мешает нам выполнять обработку прям здесь :). Но тут вопрос, будут ли проблемы с большим кол-вом соединений? Ведь мы не сохраняем их в список(очередь). Хотя по моему создание отдельных потоков, на одно процессорной машине не то что не увеличит скорость, но наоборот — уменьшить ее. Далее. Здесь используется setSocketDescriptor, который связывает объект сокета с дескриптором который получен ранее от системы. Ну а далее все как обычно. Еще стоит обратить внимание на waitForDisconnected, она заставляет нас не выходить быстро из функции, иначе будет удален tcpSocket, потому что мы объявили его не динамически. А если он будет удален, вполне возможно сокет не сможет корректно «отработать». Также если вы работаете с сокетом в отдельном потоке, waitForDisconnected заставляет не выходить из рабочей функции потока, и тем самым поток не «умирает», а он нужен, так как сокет использует его очередь сообщений, без которой он не сможет корректно разъединиться. Везде в QTcpSocket используется асинхронный режим (без потока), кроме waitForNewConnection. Мастера, прошу указать на ошибки! UPD Спасибо BRE! UPD http://www.xmind.net/share/ruzzzua/work-with-qtcpsocket/ — может кому пригодится Название: Re: Работа с QTcpSocket Отправлено: BRE от Ноябрь 02, 2009, 19:41 Поэтому способ не переопределяющий incomingConnection не подходит для многопоточных приложений. Если сокету сделать setParent( 0 ), то его можно перенести в "клиентский" поток.Мы также не можем использовать QObject->moveToThread(), потому что этот сокет имеет родителя (передается this). Главное, не забывать, что теперь мы за него отвечаем и при завершение потока его убить. Название: Re: Работа с QTcpSocket Отправлено: BRE от Ноябрь 02, 2009, 19:46 Где-то на форуме читал что deleteLater не совсем удаляет, так ли это? Почему же в официальном примере не боятся этого? :) Совсем удаляет, только чуть позже, точнее при очередном возвращении в eventloop.Как я понимаю для Windows используются асинхронные функции для работы с сокетами? Или используется какой-то дополнительный поток? Везде используется асинхронный режим (без потока). Название: Re: Работа с QTcpSocket Отправлено: Ruzzz от Ноябрь 02, 2009, 20:27 BRE, правильно ли я понимаю, что в слоте, принимающем сигнал newConnection, строка connect(clientConnection, SIGNAL(disconnected()), clientConnection, SLOT(deleteLater())); не обязательна, потому что в QTcpServer::incomingConnection(int socketDescriptor) в строке QTcpSocket *socket = new QTcpSocket(this); конструктору QTcpSocket передается this? Я думаю что да, но лучше спросить :)
Название: Re: Работа с QTcpSocket Отправлено: BRE от Ноябрь 02, 2009, 20:31 BRE, правильно ли я понимаю, что в слоте, принимающем сигнал newConnection, строка connect(clientConnection, SIGNAL(disconnected()), clientConnection, SLOT(deleteLater())); не обязательна, потому что в QTcpServer::incomingConnection(int socketDescriptor) в строке QTcpSocket *socket = new QTcpSocket(this); конструктору QTcpSocket передается this? Я думаю что да, но лучше спросить :) Это строка не обязательна.Недавно обсуждали подобную тему: http://www.prog.org.ru/topic_11091_0.html Название: Re: Работа с QTcpSocket Отправлено: brucemax от Декабрь 14, 2012, 17:18 А если сокет методом moveToThread кинуть в клиентский поток, то его ранее подключенные слоты будут выполняться в новом потоке?
Название: Re: Работа с QTcpSocket Отправлено: fantom от Декабрь 18, 2012, 16:05 Можно я вклинюсь немного, а то название темы подходящее))
Есть свой клиент — сервер. Проблема состоит в следующем. Есть класс tNet ( потомок от Qthread ) в котором написана реализация работы с сетью. Если запустить его в главном классе MainWindow, то все работает. Но по логике постоения программы, введен дополнительный класс — потомок от Qobject, в котором запускается tNet. Этот класс запускается в MainWindow. При таком построении программы, соединения с сервером не происходит, выдавая ошибку - Connect Error: The host was not found. Собственно почему так происходит, непонятно ) Название: Re: Работа с QTcpSocket Отправлено: mutineer от Декабрь 18, 2012, 16:07 Создавай тему, показывай код
|