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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: [Qt 3] Два сокета QSocketDevice в одном классе-наследнике QObject  (Прочитано 8816 раз)
qtkoder777
Частый гость
***
Offline Offline

Сообщений: 245


Просмотр профиля
« : Март 03, 2014, 08:51 »

Здравствуйте. Необходимо реализовать работу с сетью по протоколу UDP на Qt 3.
Программа должна соединяться с многими устройствами, у каждого устройства есть основной и резервный канал. Для этого написан класс NetInterface, содержащий два сокета для основного и для резервного канала.

Когда создан один сокет(setPrimaryChannel или setSecondaryChannel), работают и передача и прием.  
Если создать оба сокета, то сокеты работают только на передачу - сигнал activated при получении данных не возникает.
Выяснилось, что дело именно в сокетах - достаточно добавить в метод setPrimaryChannel строку
Код
C++ (Qt)
QSocketDevice* s=new QSocketDevice;
чтобы перестал работать прием.
Если сокеты не находятся в одном классе-наследнике QObject, то они успешно работают вместе.
Во всех примерах к Qt3 в классе только один сокет.

Является ли это каким-то известным багом Qt 3, и как его обходить?


Код
C++ (Qt)
class NetInterface : public QObject
{
   Q_OBJECT
public:
   NetInterface();
   ~NetInterface();
   void setPrimaryChannel(QHostAddress addr, int port);
   void setSecondaryChannel(QHostAddress addr, int port);
   void sendPacket(const char* packet, int size);
private:
   QSocketDevice *pSocket, *sSocket;
   QSocketNotifier *pNotifier, *sNotifier;
   QHostAddress pAddr, sAddr;
   int pPort, sPort;
private slots:
   void pDataReceived(int);
   void sDataReceived(int);
};
 
void NetInterface::setPrimaryChannel(QHostAddress addr, int port)
{
   pAddr=addr;
   pPort=port;
   pSocket=new QSocketDevice(QSocketDevice::Datagram);
   pSocket->setBlocking(false);
   pSocket->bind(addr, port);
   pNotifier = new QSocketNotifier(pSocket->socket(), QSocketNotifier::Read);
   connect(pNotifier, SIGNAL(activated(int)), SLOT(pDataReceived(int)));
}
 
void NetInterface::setSecondaryChannel(QHostAddress addr, int port)
{
   sAddr=addr;
   sPort=port;
   sSocket=new QSocketDevice(QSocketDevice::Datagram);
   sSocket->setBlocking(false);
   sSocket->bind(addr, port);
   sNotifier = new QSocketNotifier(sSocket->socket(), QSocketNotifier::Read);
   connect(sNotifier, SIGNAL(activated(int)), SLOT(sDataReceived(int)));
}
« Последнее редактирование: Март 03, 2014, 09:20 от qtkoder777 » Записан
OKTA
Гость
« Ответ #1 : Март 03, 2014, 09:30 »

А вы уверены, что можно дважды подцепиться к одному и тому же сокету?
Проверьте, что возвращает bind + по логике работы резервных каналов, резерв включается тогда, когда отпадает основной канал, а не работает постоянно + опять же если уж так надо, чтобы она работал постоянно, выделите ему отдельный порт.
« Последнее редактирование: Март 03, 2014, 09:36 от OKTA » Записан
qtkoder777
Частый гость
***
Offline Offline

Сообщений: 245


Просмотр профиля
« Ответ #2 : Март 03, 2014, 09:33 »

Что значит к одному и тому же сокету?
Создаются два сокета pSocket и sSocket. Порты у них точно разные, адреса могут быть одинаковыми.
Записан
OKTA
Гость
« Ответ #3 : Март 03, 2014, 09:39 »

Да, пардон, не туда посмотрел с портами.. хм.. тогда все еще запутаннее  Грустный
Записан
qtkoder777
Частый гость
***
Offline Offline

Сообщений: 245


Просмотр профиля
« Ответ #4 : Март 03, 2014, 09:55 »

Данные должны постоянно отправляться в оба канала.
bind и connect возвращают true, то есть вроде бы ошибок нет.
Записан
OKTA
Гость
« Ответ #5 : Март 03, 2014, 10:40 »

А сигнал activated вообще ни разу не эмитится? Нашел вот что. Мало ли  Непонимающий
Код:
Notes for Windows Users
The socket passed to QSocketNotifier will become non-blocking, even if it was created as a blocking socket. The activated() signal is sometimes triggered by high general activity on the host, even if there is nothing to read. A subsequent read from the socket can then fail, the error indicating that there is no data available (e.g., WSAEWOULDBLOCK). This is an operating system limitation, and not a bug in QSocketNotifier.
To ensure that the socket notifier handles read notifications correctly, follow these steps when you receive a notification:
Disable the notifier.
Read data from the socket.
Re-enable the notifier if you are interested in more data (such as after having written a new command to a remote server).
To ensure that the socket notifier handles write notifications correctly, follow these steps when you receive a notification:
Disable the notifier.
Write as much data as you can (before EWOULDBLOCK is returned).
Re-enable notifier if you have more data to write.
Further information: On Windows, Qt always disables the notifier after getting a notification, and only re-enables it if more data is expected. For example, if data is read from the socket and it can be used to read more, or if reading or writing is not possible because the socket would block, in which case it is necessary to wait before attempting to read or write again.
Записан
qtkoder777
Частый гость
***
Offline Offline

Сообщений: 245


Просмотр профиля
« Ответ #6 : Март 03, 2014, 10:54 »

А сигнал activated вообще ни разу не эмитится?
Ни разу.
Записан
OKTA
Гость
« Ответ #7 : Март 03, 2014, 11:26 »

Идеи кончились  Грустный
Записан
Bepec
Гость
« Ответ #8 : Март 03, 2014, 11:32 »

я б советовал не мучаться и сделать на WinApi. Скорость обработки выше и делается элементарно Показает язык
Записан
qtkoder777
Частый гость
***
Offline Offline

Сообщений: 245


Просмотр профиля
« Ответ #9 : Март 03, 2014, 11:54 »

Программа под QNX. Там только Qt3 или unix-сокеты.
Если переходить на unix-сокеты, надо ли создавать отдельный поток для прослушки каждого сокета ?
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #10 : Март 03, 2014, 19:58 »

Является ли это каким-то известным багом Qt 3, и как его обходить?
Уже сложно сказать был ли такой баг, а обойти его можно сделав класс Channel наследником QObject и в нем хранить один сокет с обвязкой. А в классе NetInterface поместить два объекта Channel.
« Последнее редактирование: Март 03, 2014, 20:51 от Old » Записан
qtkoder777
Частый гость
***
Offline Offline

Сообщений: 245


Просмотр профиля
« Ответ #11 : Март 07, 2014, 09:21 »

Отключил нескольких клиентов, и ошибка исчезла.
Кажется, что в Qt3 есть ограничение на число сокетов в одной программе.
Можно ли его изменить?
Записан
Bepec
Гость
« Ответ #12 : Март 07, 2014, 09:56 »

Мб это в QNX какие то ограничения?
Записан
OKTA
Гость
« Ответ #13 : Март 07, 2014, 10:10 »

TCP/IP limits

The number of open connections and sockets is limited only by memory and by the maximum number of file descriptors per process (see "File descriptors," above).

http://www.qnx.com/developers/docs/6.3.0SP3/neutrino/user_guide/limits.html
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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