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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Сервер, обслуживающий два клиента, но без QThread  (Прочитано 16828 раз)
G-virus
Гость
« : Февраль 19, 2010, 12:03 »

Привет всем. Пишу сервер, обслуживающий два клиента отдельно. Порылся на форуме, говорят что реализуется с помощью QThread. А можно ли как-нибудь сделать по другому, не используя класс QThread? Допустим создать два экземпляра QTcpSocket и открыть два порта. Пытался, но не получается. У меня в книге описана только двусторонняя работа (один серв, один клиент)
Записан
BRE
Гость
« Ответ #1 : Февраль 19, 2010, 12:09 »

А можно ли как-нибудь сделать по другому, не используя класс QThread?
Можно. Объект QTcpServer может обслуживать несколько подключений на одном порту и для каждого клиента создавать свой канал.

Пытался, но не получается. У меня в книге описана только двусторонняя работа (один серв, один клиент)
Показывай как пытался.  Подмигивающий
Записан
G-virus
Гость
« Ответ #2 : Февраль 19, 2010, 12:20 »

Сильно не ругайте, если говнокод написал Смеющийся
Вот main.cpp
Код
C++ (Qt)
#include <QtGui/QApplication>
#include "widget.h"
#include <QTextCodec>
#include <QMessageBox>
int main(int argc, char *argv[])
{
   QTextCodec *codec = QTextCodec::codecForName("cp1251");
   QTextCodec::setCodecForLocale(codec);
   QTextCodec::setCodecForTr(codec);
   QTextCodec::setCodecForCStrings(codec);
   QApplication a(argc, argv);
   QWidget w;
   w.setGeometry(0, 0, 0, 0);
   w.show();
   TripServer server;
   if( !server.listen( QHostAddress::Any, 6178 ) )
   {
       QMessageBox::critical(NULL, "Error", "Ошибка открытия порта 6178");
           return 1;
   }
   TripServer server2;
   if( !server2.listen( QHostAddress::Any, 6177 ) )
   {
       QMessageBox::critical(NULL, "Error", "Ошибка открытия порта 6178");
           return 1;
   }
return a.exec();
}
 
 

widget.h
Код
C++ (Qt)
#ifndef WIDGET_H
#define WIDGET_H
 
#include <QtGui/QWidget>
#include <QTcpServer>
#include <QTcpSocket>
 
class ClientSocket : public QTcpSocket
{
   Q_OBJECT
public:
   ClientSocket(QObject *parent = 0);
       int id;
 QString strA;
private slots:
   void readClient();
};
class TripServer : public QTcpServer
{
   Q_OBJECT
public:
   TripServer( QObject *parent = 0 ) : QTcpServer( parent ){}
private:
   void incomingConnection(int socketId);
};
#endif // WIDGET_H
 

widget.cpp
Код
C++ (Qt)
#include "widget.h"
 
void TripServer::incomingConnection(int socketId)
{
   ClientSocket *socket = new ClientSocket(this);
   socket->setSocketDescriptor(socketId);
 
}
 
ClientSocket::ClientSocket( QObject *parent )
       :QTcpSocket(parent)
{
   QObject::connect( this, SIGNAL( readyRead() ), this, SLOT( readClient() ) );
   QObject::connect( this, SIGNAL( disconnected() ), this, SLOT( deleteLater() ) );
}
void ClientSocket::readClient()
{
   QDataStream in(this);
   QDataStream out(this);
   in.setVersion(QDataStream::Qt_4_5);
   in >> strA;
   id = 1;
   if (strA == "Hi")
           out << id;
}
 

Вот каким-то таким образом пытался сделать  Смеющийся Но все равно это не правильно.... Грустный
Записан
BRE
Гость
« Ответ #3 : Февраль 19, 2010, 12:53 »

Не обязательно создавать несколько объектов, слушающих разные порты. Хватит и одного.
Не вижу самого клиента, как отправляешь данные?
При чтении (слот readClient) нужно дожидаться момента прихода необходимых данных, а только потом их читать и разбирать. В примерах все это есть, посмотри (bytesAvailable).
Записан
G-virus
Гость
« Ответ #4 : Февраль 19, 2010, 13:43 »

Не обязательно создавать несколько объектов, слушающих разные порты. Хватит и одного.
Не вижу самого клиента, как отправляешь данные?
При чтении (слот readClient) нужно дожидаться момента прихода необходимых данных, а только потом их читать и разбирать. В примерах все это есть, посмотри (bytesAvailable).


Клиент у меня создает объект QTcpSocket подключается к указанному ip и порту ну и передача данных, думаю это элементарно Улыбающийся Создается QDataStream out, и при нажатии кнопки отсылается данные (извиняюсь за словесное объяснение - не со своего компьютера сижу, кода нету чтобы послать). Просто при реализации сервера обслуживающего только 1 подключение, там проще. Создается 1 объект QTcpServer, и начинается прослушка порта. Как подключается клиент, слот readClient() ловит входящие пакеты. Все это прекрасно и замечательно, но только в случае с 1 подключением
Записан
BRE
Гость
« Ответ #5 : Февраль 19, 2010, 13:50 »

Подключайся несколькими клиентами к одному порту сервера. Он отработает и создаст несколько QTcpSocket для обмена с каждым клиента. И они будут асинхронно (с некоторыми оговорками) работать.
Что именно не так?  Подмигивающий
Записан
G-virus
Гость
« Ответ #6 : Февраль 19, 2010, 14:25 »

Подключайся несколькими клиентами к одному порту сервера. Он отработает и создаст несколько QTcpSocket для обмена с каждым клиента. И они будут асинхронно (с некоторыми оговорками) работать.
Что именно не так?  Подмигивающий
Я так уже пробовал, но не получается сделать так, чтобы сервер принял данные одного клиента, обработал, и передал их на другой. Может что-то забываю?
Точнее я так подумывал, как сделать отдельный QDataStream out для второго сервера (пробовал указать QDataStream out(server1) и QDataStream out(server2) но компилятор давал ошибку)
« Последнее редактирование: Февраль 19, 2010, 15:02 от G-virus » Записан
BRE
Гость
« Ответ #7 : Февраль 19, 2010, 15:15 »

Что-то я запутался что ты хочешь сделать.  Улыбающийся
Есть один сервер QTcpServer, он слушает нужный порт (6178). Когда к этому серверу подключается клиент для него создается отдельное подключение ClientSocket, через которое происходит общение: сервер <---> клиент1.
Если, к этому же серверу, через тот-же порт, подключается второй клиент, то для него создастся другое подключение ClientSocket: сервер <---> клиент2.
Эти два подключения будут работать каждый с своим клиентом.
Записан
G-virus
Гость
« Ответ #8 : Февраль 19, 2010, 15:23 »

Что-то я запутался что ты хочешь сделать.  Улыбающийся

Сори, толком не объяснил задачу. Имеется транслятор(сервер). Он принимает данные от одного клиента, обрабатывает, и передает их другому клиенту
Записан
BRE
Гость
« Ответ #9 : Февраль 19, 2010, 15:48 »

А как сервер определяет, кому что отдавать?
Например, есть 25 клиентов, они подключились к серверу, как он определяет от кого данные получать и кому отдавать?
Записан
G-virus
Гость
« Ответ #10 : Февраль 19, 2010, 16:06 »

А как сервер определяет, кому что отдавать?
Например, есть 25 клиентов, они подключились к серверу, как он определяет от кого данные получать и кому отдавать?
Хм... а хз.... А если допустим сделать чтобы серверу все равно было от кого принимать, главное отдать определенному?
Записан
BRE
Гость
« Ответ #11 : Февраль 19, 2010, 16:32 »

Хм... а хз.... А если допустим сделать чтобы серверу все равно было от кого принимать, главное отдать определенному?
Хм.  Строит глазки
Тогда можно сделать, как ты и пробовал.
Сервер открывает два порта (например 6177 и 6178). Все кто подключаются к первому порту - отправляют данные (Sender), все кто подключаются ко второму - получают результат (Recv).
Напиши класс ProccessData. Объект этого класса будет заниматься обработкой данных. Он будет один для всех (singleton).
Когда, от Sender-клиента приходят данные они помещаются в очередь объекта ProcessData, который по очереди их обрабатывает. Если данные готовы, он отсылает сигнал с готовыми данными. Объекты Recv-клиентов, этот сигнал ловят и отправляют их по сети.

InTcpServer (6177)          ProcessData            OutTcpServer (6178)
   InClient1
   InClient2      -->       обработка      -->      OutClient1
   InClient3
   InClient4

Записан
G-virus
Гость
« Ответ #12 : Февраль 19, 2010, 16:55 »

У меня получилось вроде бы правильно присоединить оба клиента. Но возник вопрос. Если я создаю два объекта QTcpServer ина разные порты. Как мне привязать QTcpSocket и QDataStream out или in в отдельности для каждого клиента?
« Последнее редактирование: Февраль 19, 2010, 20:06 от G-virus » Записан
mcrads
Гость
« Ответ #13 : Февраль 20, 2010, 18:46 »

Что-то судари вы заморачиваетесь. Посмотрите внимательно Fortune Client & Fortune Server в демках. там даже не создается новый класс наследуемый от QTcpSocket, все можно сделать стандартный сервер. смотрим например так.

QTcpServer *server = new QTcpServer
QTcpSocket *socket1;
QTcpSocket *socket2;
int i = 0;
protected void server::incomingConnection()
{
    ++i;
    if (i == 2)
    {
        socket1 = server->nextPendingConnection();
        socket2 = server->nextPendingConnection();
    }
}
все, для каждого подключения мы создали свой сокет! и потом обращаемся к нужному по мере необходимости - откуда прочитать, куда послать =)
Записан
BRE
Гость
« Ответ #14 : Февраль 20, 2010, 18:58 »

Прочитай весь тред. Подмигивающий
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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