Просмотр сообщений
|
Страниц: 1 ... 17 18 [19] 20 21
|
271
|
Qt / Работа с сетью / Re: Завершение серверного потока
|
: Октябрь 20, 2011, 11:43
|
Так да оттуда, не хочется изобретать велосипед!) то что там описано: подключение клиентов в отдельном потоке реализовано и у меня, и это работает! Я же ничего не менял глобально.. а вот отключение клиентов и завершение работы этих потоков там не приводится, писал сам! Может в этом проблема.. Что вообще эта ошибка означает??
|
|
|
272
|
Qt / Работа с сетью / Re: Завершение серверного потока
|
: Октябрь 20, 2011, 11:20
|
К сожалению не помогло..Даже наоборот, если убрать this, при закрытии приложения процесс остается висеть и грузить дико проц! Кину весь файл, глянь пожалуйста, может заметишь где собака зарыта) FortuneServer::FortuneServer() : QTcpServer() { fortunes << tr("You've been leading a dog's life. Stay off the furniture.") << tr("You've got to think about tomorrow.") << tr("You will be surprised by a loud noise.") << tr("You will feel hungry again in another hour.") << tr("You might have mail.") << tr("You cannot kill time without injuring eternity.") << tr("Computers are not intelligent. They only think they are."); numCl = 0; }
bool FortuneServer::InitializeServer(int port) { QString nP; nP.setNum(port); nPort = port; if (!listen(QHostAddress::Any, nPort)) { QMessageBox::critical(0,"Server Error","Unable to start the server"); return false; } emit MessageS("TCP-Server is listen <b>Port</b> " + nP,2); return true; }
void FortuneServer::incomingConnection(int socketDescriptor) { QString fortune = fortunes.at(qrand() % fortunes.size()); FortuneThread *thread = new FortuneThread(socketDescriptor, fortune, this); connect(thread, SIGNAL(msgToGUI(QString,int)), SIGNAL(MessageS(QString,int))); thread->numCl = ++numCl; connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start(); }
// ================================= Thread() ============================================================ // конструктор ! FortuneThread::FortuneThread(int socketDescriptor, const QString &fortune, QObject *parent) : QThread(parent), socketDescriptor(socketDescriptor), text(fortune), tcpSocket(NULL) { connect(this, SIGNAL(MessageClient(QTcpSocket*,QString,int)),SLOT(sendToClient(QTcpSocket*,QString,int))); flag = false; numCl = 0; }
void FortuneThread::run() { headl objHead; IDThr = (int)currentThreadId(); tcpSocket = new QTcpSocket(this);
if(!tcpSocket->setSocketDescriptor(socketDescriptor)) { emit error(tcpSocket->error()); emit MessageClient(tcpSocket, "<b>SERVER:</b>Error to initialization Socket!",2); } emit MessageClient(tcpSocket, "<b>SERVER:</b>Client was connected!",2); emit msgToGUI(QTime::currentTime().toString()+" <b>Client</b> " + QString().setNum(numCl) + " CONNECTED!",2);
while(!tcpSocket->waitForReadyRead(1)) { if(tcpSocket->state() == QAbstractSocket::UnconnectedState) { emit msgToGUI("<b>Client</b> DISCONNECTED!",2); delete tcpSocket; return; } } QFile file("MatrixData_" + QString().setNum(IDThr)); if(file.open(QIODevice::WriteOnly)) { while(true) { if(tcpSocket->state() == QAbstractSocket::UnconnectedState) { if(file.isOpen()) file.close(); emit msgToGUI("<b>Client</b> DISCONNECTED!",2); delete tcpSocket; return; }
if(tcpSocket->waitForReadyRead(1000)) { if(!flag) // false { timer.start(); retrRead = tcpSocket->read((char*)&objHead,sizeof(objHead)); // читаем переданную стуктуру!
if( retrRead == -1) return; if( retrRead == 0) return; }
if(tcpSocket->bytesAvailable() != objHead.sizeData) { flag = true; continue; } file.write(tcpSocket->read(objHead.sizeData));
emit MessageClient(tcpSocket, "<b>\nSize file: </b>" + QString().setNum(objHead.sizeData) + " Byte", 2); emit msgToGUI(QTime::currentTime().toString()+" <b>File is sent - </b>" + QString().setNum(timer.elapsed(),10) + " ms",2); flag = false; file.close(); } // waitForReadyRead() } // while() } // if() file.open() else { // если нельзя открыть файл msgToGUI("<b>Error</b> of the determination of the file!",2); return; } } // run()
void FortuneThread::sendToClient(QTcpSocket* pSocket, QString str, int num) // отправить Клиенту { QByteArray arrBlock; headl objHeadSendCl; objHeadSendCl.sizeData = str.size(); arrBlock.append((const char*)&objHeadSendCl, sizeof(objHeadSendCl)); arrBlock.append(str); pSocket->write(arrBlock); }
Главная форма: FormServ::FormServ(QWidget *parent) : QDialog(parent) { setupUi(this); // инициализация формы
editServ->setFocus(); QRegExp regExp("[0-9]{1,5}"); // ограниченный ввод данных editServ->setValidator(new QRegExpValidator(regExp,this)); connect(butServ, SIGNAL(clicked()), SLOT(lineEd_textPORT())); m_Serv = new FortuneServer; connect(m_Serv, SIGNAL(MessageS(QString,int)), SLOT(slotShowMessage(QString,int))); };
void FormServ::lineEd_textPORT() { bool ok; m_Serv->InitializeServer(editServ->text().toInt(&ok,10)); }
void FormServ::slotShowMessage(QString mess,int id) { if(id == 2) textEditServ->append(mess); }
|
|
|
273
|
Qt / Работа с сетью / Re: Завершение серверного потока
|
: Октябрь 20, 2011, 10:34
|
Сигнал msgToGUI() в принципе не связан с сокетом.. он просто выводит сообщение о дисконекте клиента на форму сервера!Но, если поменять ошибка все равно иногда проскакивает.. и именно, когда закрываешь приложение сервера, а не вовремя отключения/подключения клиентов или передаче файлов..! // файл QObgect.cpp QTread *QObject::thread() const { return d_func()->threadData->thread; // на этой строке вылетала ошибка !!! }
|
|
|
274
|
Qt / Работа с сетью / Re: Завершение серверного потока
|
: Октябрь 19, 2011, 11:27
|
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); Действительно это решило проблему! Огромное спасибо, andrew.k =) Вроде все работает как и задумывалось.. Клиенты нормально подключаются в отдельных потоках и передают файлы на сервер, нормально и отключаются..! Теперь стоит вопрос в скорости и надежности, а именно: 1. Обнаруживать, что клиент отключился максимально быстро, даже в момент передачи файла и завершить корректно поток, связанный с этим клиентом! После определенного тестирования возникает такая проблемка (не всегда, но пару раз вылетала программа!!!).. Если скажем 3 клиента передают одновременно файлы большого размера и в момент передачи закрыть одного из клиентов, то при завершении работы сервера вылитала ошибка в файле QObject.cpp: QTread *QObject::thread() const { return d_func()->threadData->thread; // на этой строке вылетала ошибка !!! }
Чтобы это значило? 2. Принимать файлы большого размера (около 200 Мб) также как можно быстрее! Если есть идеи как можно оптимизировать этот код, подскажите пожалуйста! void FortuneThread::run() { headl objHead; IDThr = (int)currentThreadId(); tcpSocket = new QTcpSocket(this);
if(!tcpSocket->setSocketDescriptor(socketDescriptor)) { emit error(tcpSocket->error()); emit MessageClient(tcpSocket, "<b>SERVER:</b>Error to initialization Socket!",2); } emit MessageClient(tcpSocket, "<b>SERVER:</b>Client was connected!",2); emit msgToGUI(QTime::currentTime().toString()+" <b>Client</b> " + QString().setNum(numCl) + " CONNECTED!",2);
QFile file("MatrixData_" + QString().setNum(IDThr)); if(file.open(QIODevice::WriteOnly)) { while(true) { if(tcpSocket->state() == QAbstractSocket::UnconnectedState) { delete tcpSocket; emit msgToGUI("<b>Client</b> DISCONNECTED!",2); return; }
if(tcpSocket->waitForReadyRead(1000)) { if(!flag) // false ; чтение заголовка { timer.start(); retrRead = tcpSocket->read((char*)&objHead,sizeof(objHead)); // читаем переданную стуктуру!
if( retrRead == -1) return; if( retrRead == 0) return; } if(tcpSocket->bytesAvailable() != objHead.sizeData) { flag = true; continue; } file.write(tcpSocket->read(objHead.sizeData));
emit MessageClient(tcpSocket, "<b>\nSize file: </b>" + QString().setNum(objHead.sizeData) + " Byte", 2); emit msgToGUI(QTime::currentTime().toString()+" <b>File is sent - </b>" + QString().setNum(timer.elapsed(),10) + " ms",2); flag = false; file.close(); } // waitForReadyRead() } // while() } else { // если нельзя прочитать файл msgToGUI("<b>Error</b> of the determination of the file!",2); return; } }
|
|
|
275
|
Qt / Работа с сетью / Завершение серверного потока
|
: Октябрь 18, 2011, 10:56
|
Доброго дня! Проблема в следующем.. Создаю на каждого подключаемого клиента свой поток void FortuneServer::incomingConnection(int socketDescriptor) { QString fortune = fortunes.at(qrand() % fortunes.size()); FortuneThread *thread = new FortuneThread(socketDescriptor, fortune, this); connect(thread, SIGNAL(msgToGUI(QString,int)), SIGNAL(MessageS(QString,int))); connect(thread, SIGNAL(finished()), SLOT(deleteLater()));
thread->start(); }
Функция потока: void FortuneThread::run() { tcpSocket = new QTcpSocket(this); // для каждого подключенного клиента свой СОКЕТ
if(!tcpSocket->setSocketDescriptor(socketDescriptor)) { emit error(tcpSocket->error()); emit MessageClient(tcpSocket, "<b>SERVER:</b>Error to initialization Socket!",2); } while(true) { if(tcpSocket->state() == QAbstractSocket::UnconnectedState) { tcpSocket->disconnectFromHost(); tcpSocket->waitForDisconnected(); return; // ??????!!!!!!!!!! } if(tcpSocket->waitForReadyRead(3000)) { // .... принимаем данные от клиента } // waitForReadyRead() } // while() }
Собственно вопрос как завершить правильно поток, если клиент отсоединился??! Ибо сейчас, если клиент отсоединился он больше не подключается (не вызывается incomingConnection) ! Если закоментить return, то клиент подключается, но начинает грузиться CPU!
|
|
|
276
|
Qt / 2D и 3D графика / Re: QMainWindow + OpenGL
|
: Октябрь 12, 2011, 12:15
|
Что за форум, сам вопрос задаешь и сам же на него отвечаешь (( Может кому пригодится, работает так: class DrawOpenGL; class ClientGL : public QMainWindow, public Ui::ClientGLClass { Q_OBJECT
public: ClientGL(QWidget *parent = 0, Qt::WFlags flags = 0); ~ClientGL();
DrawOpenGL *glWidget; };
В конструкторе класса ClientGL: glWidget = new DrawOpenGL(widgetGL); // где widgetGL objectName виджета widgetGL->setLayout(new QHBoxLayout); widgetGL->layout()->addWidget(glWidget);
в методах initializeGL(); resizeGL(int nWidth, int nHeight); paintGL(); задаешь нужные параметры отрисовки OpenGL Вот и все)
|
|
|
278
|
Qt / 2D и 3D графика / Re: QMainWindow + OpenGL
|
: Октябрь 11, 2011, 16:54
|
void QMainWindow::setCentralWidget ( QWidget * widget ) А в дизайнере через "Promote to".
Если я правильно понял в конструкторе главного окна (QMainWindow) добавляем: setCentralWidget(widgetGL); // где widgetGL objectName виджета в дизайнере: правой кнопкой по Главному окну -> Promote to, где выбираем "Base class name:" - QWidget "Promoted class name:" - DrawOpenGL "Header file:" - тот хедер, где описан DrawOpenGL тем самым мы свяжем главное окно с виджетом? И функции virtual void initializeGL(); virtual void resizeGL(int nWidth, int nHeight); virtual void paintGL(); должны вызываться автоматически при создании главного окна??? Или как оно должно работать?!
|
|
|
279
|
Qt / 2D и 3D графика / QMainWindow + OpenGL
|
: Октябрь 11, 2011, 14:25
|
Доброго дня) Нужно отобразить графику OpenGL в главном окне Qt: Класс главного окна: class ClientGL : public QMainWindow, public Ui::ClientGLClass { Q_OBJECT
public: ClientGL(QWidget *parent = 0, Qt::WFlags flags = 0); ~ClientGL(); };
я так понимаю надо создать еще один класс: class DrawOpenGL : public QGLWidget { Q_OBJECT
public: DrawOpenGL();
protected: virtual void initializeGL(); virtual void resizeGL(int nWidth, int nHeight); virtual void paintGL(); };
И этот класс каким-то образом увязать с главным окном.. вопрос КАК???!!! Допустим разместить через Qt Desiner, например, объект QWidget и в него выводить.. можно?? Тогда каким образом, подскажите пожалуйста?! =)
|
|
|
281
|
Qt / Общие вопросы / Re: Создание WinAPI окна с Qt формы
|
: Октябрь 07, 2011, 14:02
|
в общем работает так)) #include "servgl.h" #include <QMessageBox.h>
HINSTANCE hInst; static HGLRC hRC; // Постоянный контекст рендеринга static HDC hDC; // Приватный контекст устройства GDI
bool RegisterClass(HINSTANCE hInstance);
ServGL::ServGL(QWidget *parent, Qt::WFlags flags) : QMainWindow(parent, flags) { setupUi(this); connect(crWinGL, SIGNAL(clicked()), SLOT(slotCreateWindowGL()));
hInst = GetModuleHandle(NULL); RegisterClass(hInst); }
ServGL::~ServGL() { }
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { GLuint PixelFormat; PAINTSTRUCT ps; static PIXELFORMATDESCRIPTOR pfd= { sizeof(PIXELFORMATDESCRIPTOR), // Размер этой структуры 1, // Номер версии (?) PFD_DRAW_TO_WINDOW |// Формат для Окна PFD_SUPPORT_OPENGL |// Формат для OpenGL PFD_DOUBLEBUFFER,// Формат для двойного буфера PFD_TYPE_RGBA, // Требуется RGBA формат 32, // Выбор 16 бит глубины цвета 0, 0, 0, 0, 0, 0,// Игнорирование цветовых битов (?) 0, // нет буфера прозрачности 0, // Сдвиговый бит игнорируется (?) 0, // Нет буфера аккумуляции 0, 0, 0, 0, // Биты аккумуляции игнорируются (?) 32, // 16 битный Z-буфер (буфер глубины) 0, // Нет буфера траффарета 0, // Нет вспомогательных буферов (?) PFD_MAIN_PLANE, // Главный слой рисования 0, // Резерв (?) 0, 0, 0 // Маски слоя игнорируются (?) }; switch (message) // Тип сообщения { case WM_CREATE: hDC = GetDC(hWnd); // Получить контекст устройства для окна PixelFormat = ChoosePixelFormat(hDC, &pfd); // Найти ближайшее совпадение для нашего формата пикселов if (!PixelFormat) { MessageBox(0,TEXT("Can't Find A Suitable PixelFormat."),TEXT("Error"),MB_OK|MB_ICONERROR); PostQuitMessage(0); // Это сообщение говорит, что программа должна завершится break; // Предтовращение повтора кода } if(!SetPixelFormat(hDC,PixelFormat,&pfd)) { MessageBox(0,TEXT("Can't Set The PixelFormat."),TEXT("Error"),MB_OK|MB_ICONERROR); PostQuitMessage(0); break; } hRC = wglCreateContext(hDC); if(!hRC) { MessageBox(0,TEXT("Can't Create A GL Rendering Context."),TEXT("Error"),MB_OK|MB_ICONERROR); PostQuitMessage(0); break; } if(!wglMakeCurrent(hDC, hRC)) { MessageBox(0,TEXT("Can't activate GLRC."),TEXT("Error"),MB_OK|MB_ICONERROR); PostQuitMessage(0); break; } InitGL(); paintGL(); SwapBuffers( hDC ); // Меняем буфер (двойная буферизация) break;
case WM_DESTROY: PostQuitMessage(0); break;
case WM_PAINT: // break;
default: return (DefWindowProc(hWnd, message, wParam, lParam)); } return (0); }
bool RegisterClass(HINSTANCE hInstance) { WNDCLASS wc; // Структура класса Windows для установки типа окна wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC)WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst; wc.hIcon = NULL; wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+2); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.lpszMenuName = NULL; wc.lpszClassName = TEXT("OpenGL WinClass");
if(!RegisterClass(&wc)) { MessageBox(0,TEXT("Failed To Register The Window Class."),TEXT("Error"),MB_OK|MB_ICONERROR); return false; }
return true; }
bool ServGL::slotCreateWindowGL() { MSG msg; // Структура сообщения Windows HWND hWnd; // Сохранение дискриптора окна hWnd = CreateWindow(TEXT("OpenGL WinClass"), TEXT("OpenGL"), // Заголовок вверху окна WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME, 200, 200, // Позиция окна на экране 640, 480, // Ширина и высота окна NULL, NULL, hInst, NULL );
if(!hWnd) { MessageBox(0,TEXT("Window Creation Error."),TEXT("Error"),MB_OK | MB_ICONERROR); } ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); SetFocus(hWnd);
while (1) { // Обработка всех сообщений while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { if (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { return true; } } } }
|
|
|
282
|
Qt / Общие вопросы / Re: Создание WinAPI окна с Qt формы
|
: Октябрь 07, 2011, 09:55
|
Что делаешь и что не получается? Зачем вообще WinAPI юзать?
Задание такое дали.. Создать Qt форму на ней пару кнопок.. по нажатию на одной из них открывается WinAPI окошко, где будут рисоваться примитивы OpenGL!
|
|
|
284
|
Qt / Общие вопросы / Re: Отключение компьютера
|
: Сентябрь 13, 2011, 12:40
|
Вот, что нашел в инете.. int ShutdownWindows() { HANDLE hToken; LUID takeOwnershipValue; TOKEN_PRIVILEGES tkp; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) return 0; if (!LookupPrivilegeValue(0, SE_SHUTDOWN_NAME, &takeOwnershipValue)) return 0; tkp.PrivilegeCount = 1; tkp.Privileges[0].Luid = takeOwnershipValue; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken, false, &tkp, sizeof(TOKEN_PRIVILEGES), 0, 0); if (GetLastError()) return 0; return ExitWindowsEx(EWX_FORCE | EWX_SHUTDOWN,0); }
И это работает
|
|
|
|
|