안녕하세요.
이전 내용에서 Raspberry Pi의 Multicast로 데이터를 보내는 것을 확인했습니다. 다음 내용으로 보낸 데이터를 확인하는 것이 필요합니다. 그래서 찾던 중에 리눅스와 윈도우에서 크로스 컴파일되는 Qt 예제 코드가 있어서 확인해 보았습니다.
<이전 내용 링크 (Raspberry Pi Multicast Sender)>
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