Qt中使用QUdpSocket实现UDP通信方法

1. 简介

UDP(User Datagram Protocol,用户数据报协议)是轻量的、不可靠的、面向数据报(datagram)、无连接的协议,可以用于对可靠性要求不高的场所。
在使用Qt开发上位机或者应用程序中,需要使用到UDP通信,需要预先建立持久的socket链接,UDP每次发送数据报都需要指定目标IP地址和端口。

2. QUdpSocket类所用到的接口函数:

函数 功能
bool bind (quint16 port) 为UDP通信绑定一个端口
bool abort ( ) 释放为UDP绑定的端口
qint64 writeDatagram(QByteArray &datagram, QHostAddress &host, quint16 port) 数据报发送,形参分别为数据报,目的IP地址,目的端口号
bool hasPendingDatagram() 接收到数据报时,返回值为true
qint64 pendingDatagramSize() 返回待读取数据报的大小
qint64 readDatagram(char *data, qint64 maxSize) 读取数据报,返回读取数据报的字节数,maxSize为设置的读取字节数,还可以加上源IP和源端口号

3.收发流程

3.1 UDP发送

QUdpSocket  *udpSocket;
//端口绑定与解绑操作
quint16 port=8080;
udpSocket->bind(port);//绑定到port端口
udpSocket->abort();//用于解绑端口
//发送数据报操作
QByteArray datagram;
datagram.append(0xAA);//数据报填充字节数据

QHostAddress RemoteIP(“192.168.0.1”);//添加远端IP
quint16 RemotePort(port);//添加远端端口号

udpSocket->writeDatagram(datagram,RemoteIP,RemotePort);

3.2 UDP接收

//信号槽设置
connect(udpSocket,SIGNAL(readyRead()),this,SLOT(UDPReceive()));//添加信号与槽的连接,当主机端口接收到数据时readyRead()有效,进而触发跳转到UDPReceive()函数;其中readyRead()为Qt中QIODEVICE类中函数,UDPReceive()是需要自己编写的函数。
//字节读取
while(udpSocket->hasPendingDatagrams()){//判断有数据报接收到
	 QByteArray datagram;
     datagram.resize(udpSocket->pendingDatagramSize());//设置字节数组大小
     QHostAddress remoteIP;//接收远端IP
     quint16 remotePort;//接收远端端口号
     udpSocket->readDatagram(datagram.data(),datagram.size(),&remoteIP,&remotePort);//读取数据
    QString str=datagram.data();//将读取的数据转化为字符串
}

参考文献

《Qt 5.9 C++开发指南》王维波著,P400

发布了15 篇原创文章 · 获赞 2 · 访问量 4430
展开阅读全文

UDP给指定IP和端口传输数据包,为什么一直显示Network is unreachable: Datagram send failed

11-25

**_ UDPClient.java** package com.bill.udp.client; import java.io.IOException; import java.io.RandomAccessFile; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.InetSocketAddress; import com.bill.udp.util.UDPUtils; public class UDPClient { private static final String SEND_FILE_PATH = "D:/imgmap.jpg"; public static void main(String[] args){ long startTime = System.currentTimeMillis(); byte[] buf = new byte[UDPUtils.BUFFER_SIZE]; byte[] receiveBuf = new byte[1]; RandomAccessFile accessFile = null; DatagramPacket dpk = null; DatagramSocket dsk = null; int readSize = -1; try { accessFile = new RandomAccessFile(SEND_FILE_PATH,"r"); //构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。 dpk = new DatagramPacket(buf, buf.length,new InetSocketAddress(InetAddress.getByName("192.168.1.106"), 5000)); //创建数据报套接字,将其绑定到指定的本地地址。 dsk = new DatagramSocket(5001, InetAddress.getByName("192.168.1.106")); int sendCount = 0; while((readSize = accessFile.read(buf,0,buf.length)) != -1){ dpk.setData(buf, 0, readSize); dsk.send(dpk); // wait server response { while(true){ dpk.setData(receiveBuf, 0, receiveBuf.length); dsk.receive(dpk); // confirm server receive if(!UDPUtils.isEqualsByteArray(UDPUtils.successData,receiveBuf,dpk.getLength())){ System.out.println("resend ..."); dpk.setData(buf, 0, readSize); dsk.send(dpk); }else break; } } System.out.println("send count of "+(++sendCount)+"!"); } // send exit wait server response while(true){ System.out.println("client send exit message ...."); dpk.setData(UDPUtils.exitData,0,UDPUtils.exitData.length); dsk.send(dpk); dpk.setData(receiveBuf,0,receiveBuf.length); dsk.receive(dpk); if(!UDPUtils.isEqualsByteArray(UDPUtils.exitData, receiveBuf, dpk.getLength())){ System.out.println("client Resend exit message ...."); dsk.send(dpk); }else break; } }catch (Exception e) { e.printStackTrace(); } finally{ try { if(accessFile != null) accessFile.close(); if(dsk != null) dsk.close(); } catch (IOException e) { e.printStackTrace(); } } long endTime = System.currentTimeMillis(); System.out.println("time:"+(endTime - startTime)); } } **UDPUtils.java** package com.bill.udp.util; public class UDPUtils { private UDPUtils(){} /** transfer file byte buffer **/ public static final int BUFFER_SIZE = 50 * 1024; /** controller port **/ public static final int PORT = 50000; /** mark transfer success **/ public static final byte[] successData = "success data mark".getBytes(); /** mark transfer exit **/ public static final byte[] exitData = "exit data mark".getBytes(); public static void main(String[] args) { byte[] b = new byte[]{1}; System.out.println(isEqualsByteArray(successData,b)); } public static boolean isEqualsByteArray(byte[] compareBuf,byte[] buf){ if (buf == null || buf.length == 0) return false; boolean flag = true; if(buf.length == compareBuf.length){ for (int i = 0; i < buf.length; i++) { if(buf[i] != compareBuf[i]){ flag = false; break; } } }else return false; return flag; } public static boolean isEqualsByteArray(byte[] compareBuf,byte[] buf,int len){ if (buf == null || buf.length == 0 || buf.length < len || compareBuf.length < len) return false; boolean flag = true; int innerMinLen = Math.min(compareBuf.length, len); for (int i = 0; i < innerMinLen; i++) { if(buf[i] != compareBuf[i]){ flag = false; break; } } return flag; } } 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术工厂 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览