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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: UDP ip multicast  (Прочитано 8956 раз)
crashtua
Гость
« : Май 03, 2011, 22:39 »

Как у Qt обстоят дела с ip multicast? В стандартном классе вроде бы поддержки ip multicast нету. Там я смотрел извращались с разными библиотеками, типа winsock2.h, вот привожу пример спыжженого кода, который, к сожалению, не работает:
Код
C++ (Qt)
#ifndef UDPMRECEIVER_H
#define UDPMRECEIVER_H
 
#include <QObject>
#include <QtNetwork/QUdpSocket>
#include <winsock2.h>
#include <ws2tcpip.h>
class UDPMReceiver : public QObject
{
   Q_OBJECT
public:
   explicit UDPMReceiver(QObject *parent = 0);
   struct sockaddr_in TivaSinStruct;
   int TivaSocketId;
   int TivaPort;
   ip_mreq TivaMreq;
   QUdpSocket TivaUdpSocket;
signals:
 
public slots:
   void tiva_readTivaNetPacket();
};
 
#endif // UDPMRECEIVER_H
Код
C++ (Qt)
#include "udpmreceiver.h"
#include <stdio.h>
#include <QtGui/QMessageBox>
UDPMReceiver::UDPMReceiver(QObject *parent) :
   QObject(parent)
{
   TivaPort=3838;
   TivaUdpSocket.bind(TivaPort,QUdpSocket::ShareAddress);
   int TivaSendingFd = TivaUdpSocket.socketDescriptor();
   if(TivaSendingFd != -1)
   {
       ip_mreq mreq;
       memset(&mreq,0,sizeof(ip_mreq));
       mreq.imr_multiaddr.s_addr = inet_addr("238.38.38.38"); // group addr
       mreq.imr_interface.s_addr = htons(INADDR_ANY); // use default
       //Make this a member of the Multicast Group
       if(setsockopt(TivaSendingFd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char far *)&mreq,sizeof(mreq)) < 0)
       {
           printf("TivaNet Memship Error!");
           printf("\n");
       }
       // set TTL (Time To Live)
       unsigned int ttl = 38; // restricted to 38 hops
       if (setsockopt(TivaSendingFd, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&ttl, sizeof(ttl) ) < 0)
       {
           printf("TimeTo Live Error!");
           printf("\n");
       }
       connect(&TivaUdpSocket, SIGNAL(readyRead()), this, SLOT(tiva_readTivaNetPacket()));
   }
}
void UDPMReceiver::tiva_readTivaNetPacket()
{
   printf("in tiva_readTivaNetPacket()");
   printf("\n");
   QString OInMessage;
   QHostAddress PeerIp;
   PeerIp.setAddress(PeerIp.Any);
   quint16 por=TivaPort;
   while (TivaUdpSocket.hasPendingDatagrams())
   {
       QByteArray datagram;
       datagram.resize(TivaUdpSocket.pendingDatagramSize( ));
       TivaUdpSocket.readDatagram(datagram.data(), datagram.size(),&PeerIp,&por);
       OInMessage=datagram.data();
       printf(OInMessage.toStdString().c_str());
       printf("\n");
   }
}
Собственно, tiva_readTivaNetPacket() никогда не вызывается... Кто знает как победить злобный сокет?
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #1 : Май 04, 2011, 08:51 »

Как у Qt обстоят дела с ip multicast? В стандартном классе вроде бы поддержки ip multicast нету.
Нету инициализации мультикаста, если говорить точнее.

Вот пример реализации под Win (для краткости убираю из кода все проверки на успешное выполнение команды):
Инклуды:
Код
C++ (Qt)
#include <ws2tcpip.h>
#include <winsock2.h>

Инициализация:
Код
C++ (Qt)
   udpSocket.bind(QHostAddress("0.0.0.0"),4321,QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
   struct ip_mreq mcast;
   int opt = 1; // 0, если на собственный адрес отправлять не нужно
   int ttl = 1;
   int sd = udpSocket.socketDescriptor();
   memset(&mcast, 0, sizeof(struct ip_mreq));
   mcast.imr_multiaddr.s_addr = inet_addr("225.0.0.0");
   mcast.imr_interface.s_addr = inet_addr("0.0.0.0");
   setsockopt(sd, IPPROTO_IP, IP_MULTICAST_LOOP, (const char *)&opt, sizeof(int));
   setsockopt(sd, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&ttl, sizeof(ttl));
   setsockopt(sd, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mcast.imr_interface.s_addr, sizeof(mcast.imr_interface.s_addr));
   setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mcast, sizeof(mcast));
   connect(&udpSocket,SIGNAL(readyRead()),this,SLOT(readUdp()));
 

Отправка:
Код
C++ (Qt)
   udpSocket.writeDatagram(msg->text().toAscii(),QHostAddress("225.0.0.0"),4321);

Чтение:
Код
C++ (Qt)
void MainWindow::readUdp()
{
   quint64 size=udpSocket.pendingDatagramSize();
   QByteArray buffer;
   buffer.resize(size);
   udpSocket.readDatagram(buffer.data(),size);
   QListWidgetItem* lwi = new QListWidgetItem(buffer);
   listWidget->addItem(lwi);
}
 
« Последнее редактирование: Май 04, 2011, 08:52 от LisandreL » Записан
crashtua
Гость
« Ответ #2 : Май 04, 2011, 09:37 »

Спасибо, буду разбираться:) А то после java всякие winapi просто дикость:)
Записан
crashtua
Гость
« Ответ #3 : Май 04, 2011, 11:24 »

странно,ваш пример работает отлично только в релизе, а в дебаге не пашет... Может быть дело в либах?
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #4 : Май 04, 2011, 16:05 »

У меня работает и там и там.
Смотрите что у вас bind, setsockopt, writeDatagram возвращают.
Не ругается ли кто-нибудь из них в консоль приложения?
Какую версию Qt используете, какой компилятор?
Записан
crashtua
Гость
« Ответ #5 : Май 04, 2011, 19:20 »

1 bind
0 setsockopt
0 setsockopt
0 setsockopt
152 writeDatagram
В консоль ниче не ругается.
Qt 4.7.2, компилятор mingw 3.81(вообщем QT Sdk). На всякий случай приложу настройки проекта:
Код:
QT       += core

QT       -= gui

TARGET = UDPReceiver
CONFIG   += console
CONFIG   -= app_bundle

TEMPLATE = app
LIBS += "C:\QtSDK\mingw\lib\libws2_32.a"
LIBS += "C:\QtSDK\Desktop\Qt\4.7.2\mingw\lib\libQtGui4.a"
LIBS += "C:\QtSDK\Desktop\Qt\4.7.2\mingw\lib\libQtNetwork4.a"
SOURCES += main.cpp \
    cmessage.cpp \
    udpmulticastsocket.cpp \
    io.cpp \
    chat.cpp

HEADERS += \
    cmessage.h \
    udpmulticastsocket.h \
    io.h \
    chat.h
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #6 : Май 04, 2011, 21:33 »

1) Я либы никакие явным образом не подключал (в смысле LIBS += *.а)

2) QT       += core network

3)
Цитировать
QT       -= gui
LIBS += "C:\QtSDK\Desktop\Qt\4.7.2\mingw\lib\libQtGui4.a"
ORLY? Шокированный
Записан
crashtua
Гость
« Ответ #7 : Май 05, 2011, 15:54 »

без LIBS += "C:\QtSDK\mingw\lib\libws2_32.a" ругается на отсуствие ссылок...
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #8 : Май 06, 2011, 22:44 »

без LIBS += "C:\QtSDK\mingw\lib\libws2_32.a" ругается на отсуствие ссылок...
Да, наврал.
LIBS += libwsock32
Записан
crashtua
Гость
« Ответ #9 : Май 08, 2011, 16:27 »

создал новый проект, и в дебаге и в релизе нормально работает.... Мистика...
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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