행복한 하루

Qt를 이용한 멀티캐스트 수신 코드 및 테스트 (Multicast Receiver) 본문

Programming/Qt

Qt를 이용한 멀티캐스트 수신 코드 및 테스트 (Multicast Receiver)

변화의 물결 2022. 12. 2. 16:57

 

 

안녕하세요.

 

 이전 내용에서 Raspberry Pi의 Multicast로 데이터를 보내는 것을 확인했습니다. 다음 내용으로 보낸 데이터를 확인하는 것이 필요합니다. 그래서 찾던 중에 리눅스와 윈도우에서 크로스 컴파일되는 Qt 예제 코드가 있어서 확인해보았습니다.

<이전 내용 링크 (Raspberry Pi Multicast Sender)>

 

Raspberry Pi4를 이용한 멀티캐스트 송신 코드 및 테스트 (Multicast Sender)

안녕하세요. IPTV나 네트워크 쪽으로 통신 프로그램할 경우가 아니면 주로 사용하는 방식은 아니지만 이번에 확인할 일이 있어서 찾아본 내용 공유드립니다. 송신부는 C 프로그램으로 테스트하

remnant24c.tistory.com


1. Receiver 소스 확인

 - Receiver 클래스에서 단순한 UI 구성과 함수를 생성해서 작동하도록 되어 있습니다.

 - 이전 내용(Sender)에서 멀티캐스트 그룹 주소와 같은 동일한 그룹 주소를 입력합니다.

 - 별도로 UI 파일을 생성하지 않고 생성자 내에서 코드로 화면 UI를 만듭니다. 

Receiver::Receiver(QWidget *parent)
    : QDialog(parent),
      groupAddress4(QStringLiteral("225.192.0.10")),
      groupAddress6(QStringLiteral("ff12::2115"))
{
    statusLabel = new QLabel(tr("Listening for multicast messages on both IPv4 and IPv6"));
    auto quitButton = new QPushButton(tr("&Quit"));

    auto buttonLayout = new QHBoxLayout;
    buttonLayout->addStretch(1);
    buttonLayout->addWidget(quitButton);
    buttonLayout->addStretch(1);

    auto mainLayout = new QVBoxLayout;
    mainLayout->addWidget(statusLabel);
    mainLayout->addLayout(buttonLayout);
    setLayout(mainLayout);

    setWindowTitle(tr("Multicast Receiver"));

  

 - udpsocket4와 udpsocket6에 50000 포트 등 설정한 후 Bind 해서 소켓에 할당받습니다. 그리고 멀티캐스트 그룹에 udpSocket4를 추가합니다. 

    udpSocket4.bind(QHostAddress::AnyIPv4, 50000, QUdpSocket::ShareAddress);
    udpSocket4.joinMulticastGroup(groupAddress4);

    if (!udpSocket6.bind(QHostAddress::AnyIPv6, 50000, QUdpSocket::ShareAddress) ||
            !udpSocket6.joinMulticastGroup(groupAddress6))
        statusLabel->setText(tr("Listening for multicast messages on IPv4 only"));

 - 소켓에 데이터가 들어오면 읽을 수 있도록 readyRead() 시그널과 처리할 함수(processPendingDatagrams)를 연결시킵니다.

    connect(&udpSocket4, SIGNAL(readyRead()),
            this, SLOT(processPendingDatagrams()));
    connect(&udpSocket6, &QUdpSocket::readyRead, this, &Receiver::processPendingDatagrams);
    connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));

 

 - 받은 데이터가 있을 때까지 루프를 돌면서 받은 데이터 크기에 맞게 배열에 맞게 사이즈를 조절하면서 데이터를 받은 후 문자열로 출력하는 함수로 구현되어 있습니다. Qt4와 다르게 Qt5, 6 버전에서는 QNetworkDatagram 클래스를 사용하고 있습니다. 그래서 Qt 버전에 맞게 코드를 사용하셔야 할 것 같습니다.

 

void Receiver::processPendingDatagrams()
{
    QByteArray datagram;

    // using QUdpSocket::readDatagram (API since Qt 4)
    while (udpSocket4.hasPendingDatagrams()) {
        datagram.resize(int(udpSocket4.pendingDatagramSize()));
        udpSocket4.readDatagram(datagram.data(), datagram.size());
        statusLabel->setText(tr("Received IPv4 datagram: \"%1\"")
                             .arg(datagram.constData()));
    }

    // using QUdpSocket::receiveDatagram (API since Qt 5.8)
    while (udpSocket6.hasPendingDatagrams()) {
        QNetworkDatagram dgram = udpSocket6.receiveDatagram();
        statusLabel->setText(statusLabel->text() +
                             tr("\nReceived IPv6 datagram from [%2]:%3: \"%1\"")
                             .arg(dgram.data().constData(), dgram.senderAddress().toString())
                             .arg(dgram.senderPort()));
    }
}

2. 실행하기

 - 컴파일 환경은 Window10,  Qt5.12.12,  MinGW 7.30 64 bit에서 작업했습니다.

 - 처음 컴파일하고 실행하면, 수신 대기하고 있는 상태입니다.

 

 - Raspberry Pi (Sender)에서 데이터를 그룹에 보내면 Qt Client(Receiver)에 송신한 문자열이 UI에 출력되는 것을 확인할 수 있습니다.

 

감사합니다.

 

 

<참고사이트>

1. Multicast Receiver Example

https://doc.qt.io/qt-5/qtnetwork-multicastreceiver-example.html

2. 소켓 프로그래밍. (Socket Programming)

https://recipes4dev.tistory.com/153

3. QUdpSocket Class

https://doc.qt.io/qt-5/qudpsocket.html#readDatagram

multicast.zip
0.01MB

 

 

Comments