背景:
我有下面的C++代码,它在26009
端口上侦听UDP数据包,然后输出接收到的数据包
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
udpSocket.bind(26009); //the port that GUI listens (26009)
connect(&udpSocket, SIGNAL(readyRead()), this, SLOT(readyRead()));
}
void MainWindow::readyRead(){
QByteArray datagram;
do {
datagram.resize(udpSocket.pendingDatagramSize());
udpSocket.readDatagram(datagram.data(), datagram.size());
} while (udpSocket.hasPendingDatagrams());
qDebug() << "Message: " << datagram;
}
在客户端,这是一个
unicast
20 udp
数据包的C代码:hi0,hi1,... hi19:int main(void){
int i;
char msg[5] = {'\0'};
for(i=0; i<20; i++){
snprintf(msg, 4, "hi%d", i);
send_unicast("192.168.5.1", msg, 26009);
memset(msg, 0, sizeof msg);
}
return 0;
}
void send_unicast(char IPaddr[16], char* message, uint16_t destPort){
struct sockaddr_in si_other;
int s, slen = sizeof(si_other);
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){
fprintf(stderr, "socket() failed - line817\n");
exit(1);
}
memset((char *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(destPort);
if (inet_aton(IPaddr, &si_other.sin_addr) == 0) {
fprintf(stderr, "inet_aton() failed - line 825\n");
exit(1);
}
if (sendto(s, message, 512, 0, (struct sockaddr *) &si_other, slen) == -1){
fprintf(stderr, "sendto() failed - line830\n");
exit(1);
}
close(s);
}
我在不同的Linux设备上运行C++(服务器)和C(客户端)代码。
问题:
C代码可以正常工作并生成数据包。我在Wireshark上看到,数据包是在接收端(C++)上接收的。
但是,上面的C++代码无法正确接收(或处理)数据包,以某种方式对于代码来说处理太快了,我只能看到一对输出,例如
hi5
hi14
如果使用C代码(添加
sleep(1)
)大大降低了传输频率,则C++代码会很好地输出数据包。问题:
我使用收到的UDP数据包来更新有关GUI(Qt)的某些信息。我猜想
slot
会导致速度变慢,如果我使用pthread
来侦听数据包,则该代码将处理流量,但是线程如何需要通知主类,以便GUI可以进行相应的更新?总而言之,您如何建议修改C++代码,以便它可以处理快速的数据通信并通知GUI更新?
最佳答案
我希望在MainWindow的readyRead函数中,这将是一个问题:-
QByteArray datagram;
do {
qint64 dSize = udpSocket.pendingDatagramSize();
datagram.resize(dSize);
udpSocket.readDatagram(datagram.data(), dSize);
} while (udpSocket.hasPendingDatagrams());
如果第一个数据包是8个字节长,则将QByteArray设置为8个字节并读取数据。
在读取8个字节时,如果接收到6个字节,则第二次在该循环中调用字节数组的resize,但是这一次会将其从8个字节减少到6个并读取6个字节,从而丢弃您先前读入的数据。
建议您不要将QByteArray调整大小,而是将数据附加到其上:-
QByteArray datagram;
do
{ datagram.append(udpSocket.pendingDatagramSize());
udpSocket.readDatagram(datagram.data(), datagram.size());
}while (udpSocket.hasPendingDatagrams());