Qt网络通信(TCP/UDP)
目录
一、TCP通信
1.QTcpServer
2.QTcpSocket
3.TCP通信基本流程
4.示例
二、UDP通信
1.QUdpSocket
2.UDP通信基本流程
3.发送形式
4.示例
一、TCP通信
QTcpServer和QTcpSocket是Qt中用于实现TCP通信的两个类。
1.QTcpServer
QTcpServer类用于创建TCP服务器,监听指定端口,等待客户端连接。
①常用监听接口:
- listen():开始监听指定的IP地址和端口,返回是否监听成功。
- isListening():返回服务器是否处于监听状态。
②常用连接接口:
- nextPendingConnection():在槽函数中调用,用于获取与新连接的客户端对应的QTcpSocket对象。
- close():停止监听。
③QTcpServer常用信号:
- newConnection:当有新的客户端连接时,会发射该信号。
- acceptError(socketError):当接受一个新的连接时发生了错误,就发射此信号,参数socketError描述错误信息。
2.QTcpSocket
QTcpSocket类用于建立TCP连接并进行数据传输,既可以作为客户端连接服务器,也可以作为服务器端与客户端通信。
①常用连接接口:
- connectToHost():用于连接到指定的服务器,支持异步连接,连接成功后会发射connected信号。
- waitForConnected():阻塞式连接函数,等待连接成功或失败后才返回。
- disconnectFromHost():断开与主机的连接。
②常用数据传输接口:
- write():向连接端写入数据。
- read()、readAll():用于从接收缓冲区读取数据。当有新数据进入缓冲区时,会发射readyRead信号。
③常用状态获取接口:
- state():获取当前套接字的状态。
- peerAddress()、peerPort():获取连接端的IP地址和端口号。
④QTcpSocket常用信号:
- connected:当连接成功建立时,发射该信号。
- disconnected:当连接断开时,发射该信号。
- readyRead:当有数据可读时,发射该信号。
- errorOccurred(socketError):当连接发生错误时,发射该信号。
3.TCP通信基本流程
①服务器端:
创建QTcpServer对象---启动服务器监听---处理新连接请求---数据传输---关闭连接
- 创建QTcpServer对象,用于监听客户端的连接请求。
- 调用QTcpServer对象的listen()函数,指定要监听的IP地址和端口号,开始监听客户端的连接请求。
- 当有客户端的连接请求时,QTcpServer会发射newConnection信号。在对应的槽函数中,调用nextPendingConnection()函数可以获取与客户端连接的QTcpSocket对象。
- 通过获取到的QTcpSocket对象,可以使用write()函数向客户端发送数据,当有新数据可读时,QTcpSocket会发射readyRead信号,在对应的槽函数中可以使用read()或readAll()函数读取客户端发送的数据。
- 当通信结束时,调用QTcpSocket的close()函数关闭与客户端的连接。
②客户端:
创建QTcpSocket对象---连接服务器---数据传输---关闭连接
- 创建QTcpSocket对象,用于与服务器进行通信。
- 调用QTcpSocket的connectToHost()函数,指定服务器的IP地址和端口号,发起连接请求。
- 连接成功后,可以使用write()函数向服务器发送数据,当有新数据可读时,QTcpSocket会发射readyRead信号,在对应的槽函数中可以使用read()或readAll()函数读取服务器发送的数据。
- 当通信结束时,调用QTcpSocket的close()函数关闭与服务器的连接。
4.示例
服务器端主要代码:
QTcpServer *m_server;
QTcpSocket *m_tcp;
m_server = new QTcpServer(this);
//设置服务器监听
quint16 port = 9999;
m_server->listen(QHostAddress::Any,port);
qDebug()<<"服务器已启动!";
//检测新的客户端连接
connect(m_server,&QTcpServer::newConnection,this,[=]{
m_tcp = m_server->nextPendingConnection();
qDebug()<<"成功和客户端连接...";
//检测客户端数据
connect(m_tcp,&QTcpSocket::readyRead,this,[=]{
QString str = m_tcp->readAll();
qDebug()<<"客户端:"<<str;
});
//检测客户端断开连接
connect(m_tcp,&QTcpSocket::disconnected,this,[=]{
qDebug()<<"客户端断开连接...";
m_tcp->deleteLater();
});
});
//发送数据
QString str = "message";
m_tcp->write(str.toUtf8());
qDebug()<<"服务器:"<<str;
客户端主要代码:
QTcpSocket *m_tcp;
m_tcp = new QTcpSocket(this);
//连接服务器
QString ip = "127.0.0.1";
quint16 port = 9999;
m_tcp->connectToHost(QHostAddress(ip),port);
//检测和服务器成功连接
connect(m_tcp,&QTcpSocket::connected,this,[=]{
qDebug()<<"服务器连接成功!";
});
//检测和服务器断开连接
connect(m_tcp,&QTcpSocket::disconnected,this,[=]{
qDebug()<<"服务器断开连接...";
});
//检测服务器数据
connect(m_tcp,&QTcpSocket::readyRead,this,[=]{
QString str = m_tcp->readAll();
qDebug()<<"服务器:"+str;
});
//发送数据
QString str = "message";
m_tcp->write(str.toUtf8());
qDebug()<<"客户端:"+str;
//断开连接
m_tcp->close();
参考:
基于TCP的Qt网络通信 | 爱编程的大丙
二、UDP通信
在Qt中进行UDP通信主要通过QUdpSocket类来实现。
1.QUdpSocket
①常用接口:
- bind():用于将套接字绑定到指定的本地地址和端口,以便接受数据报。
- joinMulticastGroup():让套接字加入多播组以接收多播数据。
- leaveMulticastGroup():让套接字离开多播组。
- pendingDatagramSize():返回下一个可读数据报大小,便于读取准备。
- readDatagram():读取数据报并存入缓冲区,同时可获取发送方的地址和端口信息。
- writeDatagram():向指定的地址和端口发送数据报。
②常用信号:
- readyRead:当有数据报可读时发出信号,通知程序可以读取数据。
- stateChanged:套接字状态改变时发出,可据此处理状态相关逻辑。
- error:套接字发生错误时发出,便于错误处理。
2.UDP通信基本流程
①发送端:
创建套接字---发送数据---关闭套接字
- 使用QUdpSocket类创建一个UDP套接字对象。
- 使用writeDatagram()函数发送数据报,指定目标IP地址和端口号。
- 在数据发送完成后,关闭套接字以释放资源。
②接收端:
创建套接字---绑定端口---接收数据---关闭套接字
- 使用QUdpSocket类创建一个UDP套接字对象。
- 使用bind函数绑定本地端口,用于接收数据报。
- 当有数据报到达时,readyRead信号会被触发,在对应的槽函数中使用readDatagram()函数读取数据。
- 在数据接收完成后,关闭套接字以释放资源。
3.发送形式
单播:发送端向一个特定的接收端发送数据,需要指定接收端的IP地址和端口号。
QUdpSocket socket;
socket.writeDatagram(data, QHostAddress("192.168.1.100"), 7777);
广播:将数据报发送到广播地址,同一网络中的所有设备都会接收到广播数据报,但只有那些运行了相应接收程序并监听特定端口的设备才会处理这些数据报。
QUdpSocket socket;
socket.writeDatagram(data, QHostAddress::Broadcast, 7777);
组播:加入组播组后发送数据报,只有组内成员能接收。
QUdpSocket socket;
socket.joinMulticastGroup(QHostAddress("224.0.0.100"));
socket.writeDatagram(data, QHostAddress("224.0.0.100"), 7777);
4.示例
QUdpSocket *m_udp;
m_udp = new QUdpSocket(this);
//绑定本地端口
quint16 port = 8888;
if(m_udp->bind(port))
qDebug()<<"已成功绑定:"+QString::number(m_udp->localPort());
else
qDebug()<<"绑定失败";
//bind(port,QAbstractSocket::ReuseAddressHint)
//使套接字能尝试重新绑定已被占用的地址和端口
//检测是否有数据报可读
connect(m_udp,&QUdpSocket::readyRead,this,[=]{
while (m_udp->hasPendingDatagrams()) {
QByteArray buffer;
buffer.resize(m_udp->pendingDatagramSize());
QHostAddress tar_ip;
quint16 tar_port;
m_udp->readDatagram(buffer.data(),buffer.size(),&tar_ip,&tar_port);
QString str = QString("[%1-%2]: ").arg(tar_ip.toString()).arg(tar_port);
str += buffer.data();
qDebug()<<str;
}
});
/*如果不使用while循环,当有多个数据报等待处理时,
每次调用m_udp->readDatagram只会读取一个数据报。*/
//单播
QString tar_ip = "127.0.0.1";
quint16 tar_port = 8888;
QString str = "message";
m_udp->writeDatagram(str.toUtf8(),QHostAddress(tar_ip),tar_port);
qDebug()<<"[out]: "<<str;
//广播
quint16 tar_port = 8888;
QString str = "message";
m_udp->writeDatagram(str.toUtf8(),QHostAddress::Broadcast,tar_port);
qDebug()<<"[broadcast]: "<<str;