Russian Qt Forum
Май 19, 2024, 10:52 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Работа с сетью  (Прочитано 8351 раз)
demaker
Птица говорун
*****
Offline Offline

Сообщений: 960


Просмотр профиля
« : Апрель 22, 2011, 11:02 »

Помогите Непонимающий Выдается ошибка - хочу написать сервер и чтобы он начинал работать по нажатию кнопки, при этом вынес сервер в отдельный поток.
Код:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QNativeSocketEngine(0x9dae6e8), parent's thread is MyServerThread(0x9c47180), current thread is QThread(0x9bfc838)
Вот код:

MyServer.CCP
Код
C++ (Qt)
==========================================
MyServer::MyServer(QWidget *pwgt)
{
   m_ptxt = new QTextEdit;
   pb_start = new QPushButton("START");
 
   ServerThread = new MyServerThread; //QThread
 
   m_ptxt->setReadOnly(true);
 
   QVBoxLayout* pvbxLayout = new QVBoxLayout;
   pvbxLayout->addWidget(new QLabel("<H1>Server</H1>"));
   pvbxLayout->addWidget(m_ptxt);
   pvbxLayout->addWidget(pb_start);
   setLayout(pvbxLayout);
 
   connect(pb_start,SIGNAL(clicked()),ServerThread,SLOT(start()));
   connect(ServerThread,SIGNAL(signal_errorServer(QString)),m_ptxt,SLOT(append(QString)));
   connect(ServerThread,SIGNAL(signal_New_Connection(QString)),m_ptxt,SLOT(append(QString)));
}
 
MyServerThread::MyServerThread()
{
   m_nNextBlockSize = 0;
   nPort = 502;
 
   m_ptcpServer = new QTcpServer;
   m_ptcpServer->moveToThread(this);
}
 
void MyServerThread::run()//(int nPort, QWidget* pwgt /*=0*/): QWidget(pwgt),m_nNextBlockSize(0)
{
 
   /* OBRABOTKA OSHIBKI SOEDINENIA */
   if(!m_ptcpServer->listen(QHostAddress::Any, nPort))
   {
       emit signal_errorServer(m_ptcpServer->errorString());
       m_ptcpServer->close();
       return;
   }
   connect(m_ptcpServer, SIGNAL(newConnection()), this, SLOT(slotNewConnection()));*/
   exec();
}
 
/*virtual*/
void MyServerThread::slotNewConnection()
{
   QTcpSocket* pClientSocket = m_ptcpServer->nextPendingConnection();
   connect(pClientSocket, SIGNAL(disconnected()), pClientSocket, SLOT(deleteLater()) );
   connect(pClientSocket, SIGNAL(readyRead()), this, SLOT(slotReadClient()) );
   emit signal_New_Connection("New connection");
}
 
void MyServerThread::slotReadClient()
{
       QTcpSocket* pClientSocket = (QTcpSocket*)sender();
       Buffer_IN.clear();
       while( pClientSocket->bytesAvailable() )
             Buffer_IN += pClientSocket->readAll();
 
      CheckUp_Answer();
      sendToClient(pClientSocket, Buffer_OUT);
}
 
void MyServerThread::sendToClient(QTcpSocket * pSocket, const QByteArray &arOut)
{
   pSocket->write(arOut);
}
 
void MyServerThread::CheckUp_Answer()
{
           for(int i = 1;i <= 200 ;i++)
               {
                   Buffer_OUT[i+8] = 2*i;
               }
}
 
MyServer.H
Код
C++ (Qt)
======================================
class MyServerThread: public QThread
{
   Q_OBJECT
 
private:
   int nPort;
   QByteArray Buffer_IN,
              Buffer_OUT;
 
   QTcpServer * m_ptcpServer;
 
private:
   void sendToClient(QTcpSocket* pSocket, const QByteArray& arOut);
   void CheckUp_Answer();
 
public:
   MyServerThread();
   void run();
signals:
   void signal_New_Connection(QString);
   void signal_errorServer(QString);
 
public slots:
   virtual void slotNewConnection();
           void slotReadClient();
};
//**********************************************************************
class MyServer : public QWidget
{
   Q_OBJECT
 
private:
   MyServerThread *ServerThread;
 
   QTextEdit * m_ptxt;
   QPushButton *pb_start;
 
public:
   MyServer(QWidget* pwgt = 0);
};
 
« Последнее редактирование: Апрель 22, 2011, 11:25 от Пантер » Записан
blood_shadow
Гость
« Ответ #1 : Апрель 22, 2011, 11:53 »

ты сервер переместил в другой поток:
Код
C++ (Qt)
m_ptcpServer->moveToThread(this);
 
слот slotNewConnection() вызывается в главном потоке, потому вся проблема в
ф-ции m_ptcpServer->nextPendingConnection(); она создает QTcpSocket как потомок
твоего m_ptcpServer, но пытается его создать в главном потоке, идею улавливаешь?
нельзя создавать потомка и родителя в разных потоках, о чем тебе и сказали:
Код:
QObject: Cannot create children for a parent that is in a different thread.

Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 960


Просмотр профиля
« Ответ #2 : Апрель 22, 2011, 12:04 »

 ???А почему он вызвается в главном потоке, когда я создаю его в конструкторе потока MyServerThread Непонимающий
Что мне нужно сделать???
Записан
blood_shadow
Гость
« Ответ #3 : Апрель 22, 2011, 12:33 »

???А почему он вызвается в главном потоке, когда я создаю его в конструкторе потока MyServerThread Непонимающий
Что мне нужно сделать???
MyServerThread - создается в главном потоке, это только обертка для потока, другой поток на самом деле
имеет место только в run(), то есть объект MyServerThread живет в основном потоке и слот slotNewConnection()
вызывается для объекта с основного потока
если чесно я неоч понимаю что надо делать, но можно сделать вот что:
сравни указатели this в MyServerThread и MyServerThread->thread(), если они разные то поменяешь
m_ptcpServer->moveToThread(this->thread()) и
connect(m_ptcpServer, SIGNAL(newConnection()), this->thread(), SLOT(slotNewConnection()));
Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 960


Просмотр профиля
« Ответ #4 : Апрель 22, 2011, 12:42 »

 :)Сча попробую
Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 960


Просмотр профиля
« Ответ #5 : Апрель 22, 2011, 12:46 »

Попробовал
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTcpServer(0x8e0f880), parent's thread is QThread(0x8d96838), current thread is MyServerThread(0x8de1180)
 Грустный Непонимающий
Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 960


Просмотр профиля
« Ответ #6 : Апрель 22, 2011, 12:49 »

Наверное надо делать как в Fortune Server Thread примерах Qt Непонимающий
создать
отдельно Окно(Qwidget),Server(QTcpServer) и ServerThread(QThread) - 3 объета  Непонимающий Непонимающий
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #7 : Апрель 22, 2011, 13:04 »

Код
C++ (Qt)
MyServerThread::MyServerThread()
{
   m_nNextBlockSize = 0;
   nPort = 502;
}
 
void MyServerThread::run()//(int nPort, QWidget* pwgt /*=0*/): QWidget(pwgt),m_nNextBlockSize(0)
{
   m_ptcpServer = new QTcpServer();
 
   /* OBRABOTKA OSHIBKI SOEDINENIA */
   if(!m_ptcpServer->listen(QHostAddress::Any, nPort))
   {
       emit signal_errorServer(m_ptcpServer->errorString());
       m_ptcpServer->close();
       return;
   }
   connect(m_ptcpServer, SIGNAL(newConnection()), this, SLOT(slotNewConnection()));*/
   exec();
}
 
 

Только вместо QTcpServer можно (нужно) сделать свой класс типа MyServer: public QTcpServer
в котором реализовать слот slotReadClient .


Код
C++ (Qt)
 
//*.h
 
class MyServer : public QTcpServer
{
...
...
 
private slots:
    void slotReadClient();
...
}
 
void MyServer::slotReadClient()
{
       QTcpSocket* pClientSocket = (QTcpSocket*)sender();
       Buffer_IN.clear();
       while( pClientSocket->bytesAvailable() )
             Buffer_IN += pClientSocket->readAll();
 
      CheckUp_Answer();
      sendToClient(pClientSocket, Buffer_OUT);
}
 

И создавать в ::run() не QTcpServer , а MyServer.

Как то так, думаю идея ясна.
« Последнее редактирование: Апрель 22, 2011, 13:11 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
mutineer
Гость
« Ответ #8 : Апрель 22, 2011, 13:09 »

2 kuzulis
Ну и где-то еще удалять m_ptcpServer
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #9 : Апрель 22, 2011, 13:10 »

Ну да, естественно.
Записан

ArchLinux x86_64 / Win10 64 bit
blood_shadow
Гость
« Ответ #10 : Апрель 22, 2011, 13:19 »

у меня появилась еще идея:
Код
C++ (Qt)
void MyServerThread::run()//(int nPort, QWidget* pwgt /*=0*/): QWidget(pwgt),m_nNextBlockSize(0)
{
   connect(m_ptcpServer, SIGNAL(newConnection()), this, SLOT(slotNewConnection()));
 
   forever {
        m_ptcpServer = new QTcpServer();
 
        {
              QMutexLocker locker(&mutex);
              if (!pendingSocket)
                   waitCondition.wait(&mutex)
              socket = m_ptcpServer.nextPendingConnection();
              pendingSocket = false;
        }
 
        /* OBRABOTKA OSHIBKI SOEDINENIA */
        if(!m_ptcpServer->listen(QHostAddress::Any, nPort))
       {
           emit signal_errorServer(m_ptcpServer->errorString());
           m_ptcpServer->close();
           return;
       }
   }
 
}
 

Код
C++ (Qt)
void MyServerThread::slotNewConnection()
{
   mutex.lock();
   pendingSocket = true;
   mutex.unlock();
   waitCondition.wakeOne();
}
 

Идея такова pendingSocket == 0(по умолчанию) waitCondition(QWaitCondition) усыпляет вторичный поток, потом когда
появляется новый сокет испускается сигнал slotNewConnection() и будиться вторичный поток waitCondition.wakeOne();
далее во втор. потоке мы получаем наш новый сокет nextPendingConnection(); доступ к переменной защищаем с помощью
мьютекса
Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 960


Просмотр профиля
« Ответ #11 : Апрель 22, 2011, 13:39 »

 :)Попробуем
Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 960


Просмотр профиля
« Ответ #12 : Апрель 25, 2011, 10:57 »

Спасибо,заработало  Улыбающийся

А вот почему надо создавать было дочерний объет???Подскажите Улыбающийся
Записан
blood_shadow
Гость
« Ответ #13 : Апрель 25, 2011, 14:43 »

Спасибо,заработало  Улыбающийся

А вот почему надо создавать было дочерний объет???Подскажите Улыбающийся
потому что, объект созданный в ф-ции run создается в дочерном потоке, а сам же объект
MyServerThread создается в родительском и потому все ф-ции(слоты) вызываются в родительском
потоке для твоего MyServerThread
тут почитай - http://habrahabr.ru/blogs/qt_software/115830/ две части
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.309 секунд. Запросов: 19.