在Qt中网络编程主要由Qt Network模块来编写基于TCP/Ip的网络程序,其中提供了许多的类:
可以点击该链接查看:Qt网络C++类|Qt网络 5.15.12
常见的有:
QTcpServer | 基于 TCP 的服务器 |
QTcpSocket | TCP 套接字 |
QUdpSocket | UDP 套接字 |
QDtls | 此类为 UDP 套接字提供加密 |
QHostAddress | IP地址 |
QHostInfo | 用于主机名查找的静态函数 |
QLocalServer | 基于本地套接字的服务器 |
QLocalSocket | 本地插座 |
QNetworkAccessManager | 允许应用程序发送网络请求和接收答复 |
QNetworkCacheMetaData | 缓存信息 |
QNetworkDatagram | UDP 数据报的数据和元数据 |
QNetworkInterface | 列出主机的 IP 地址和网络接口 |
QNetworkProxy | 网络层代理 |
使用时:需要在pro文件中添加 QT +=network
Socket(套接字)
套接字由 ip和端口号组成 ip指定主机 端口指定主机的一个程序,通过套接字来实现网络中两台主机的通信。
TCP
TCP是用于数据传输的低级网络协议 ,它是一种可靠的、面向流的、面向连接的传输协议。它特别适合数据的连续传输。是一种面向数据流何连接的可靠的传输协议。
TCP分为客户端(TCP Client)和服务器端(TCP Server),在任何数据传输之前,必须建立一个TCP连接到远程的主机和端口上
TCP的两个类:
- QTcpSocket (TCP套接字)
- QTcpServer(TCP服务器)
注意:QTcpSocket是基于流进行传输的
QTcpSocket类 :
QTcpSocket 继承自QAbstractSocket,为TCP提供一个接口
常用的函数:
peer:是对使用TCP协议连接在一起的主机的统称
在任何时候peer都可以关闭连接,这样数据传输就会立刻停止
localAddress() | 本地套接字的主机地址(如果可用),否则返回空 等价于QHostAddress::LocalHost(127.0.0.1)用于连接本地主机 |
localPort() | 返回本地套接字的主机端口号,否则返回0 |
peerAddress() | 如果套接字处于连接状态,返回连接的对等方的地址,否则返回NULL |
peerName() | 返回由connectToHost()指定的对等方的名称 |
peerPort() | 如果套接字处于连接状态,返回连接的对等方的端口 |
connectToHost() | 尝试与给定端口上的主机名建立连接。协议参数可用于指定要使用的网络协议(例如。IPv4 或 IPv6)。 |
discinnectFromHost() | 尝试关闭套接字。如果有挂起的数据等待写入,QABstractSocket 将进入 Closesing State并等待所有数据都写入完毕 |
error() | 返回上次发生的错误类型。 |
flush() | 此函数尽可能多地从内部写入缓冲区写入基础网络套接字,而不会阻塞 |
isValid() | 如果套接字有效且可供使用,返回true否则返回False |
proxy() | 返回此套接字的网络代理 |
readBufferSize() | 返回内部读取缓冲区的大小 |
read() | 读取数据 |
write() | 写入数据 |
readDate() | 读取数据 |
readLineData() | 读取一行数据 |
writeData() | 写数据 |
bytesAvailable() | 返回可用于读取的字节数 |
setLocalAddress() | 设置地址 |
setLocalPort() | 设置端口号 |
setPeerAddress() | 设置连接端的地址 |
setPeerName() | 设置连接方的主机名 |
setPeerPort() | 设置连接方的端口 |
setProxy() | 设置网络代理 |
setReadBufferSize() | 设置内部读取缓冲区的大小 |
waitForBytesWrite(int msecs) | 此功能将一直阻塞,直到至少一个字节写入套接字并发出 bytesWrite() 信号 |
waitForReadyRead(int msecs) | 此功能将阻止,直到有新数据可供读取并且发出 readyRead() 信号 |
waitForConnected(int msecs) | 等待直到套接字连接完毕,建立连接返回true 否则返回false |
waitForDisConnected(int msecs) | 等待直到套接字断开连接 |
信号:
connected() | 成功建立连接后发出 |
disconnected() | 断开连接后发出 |
errorOccured() | 发生错误后发出(Qt 5.15中引入) |
readyRead() | 每次有新的数据块到达时都会发出 |
QNetworkProxy::ProxyType:
QNetworkProxy::NoProxy | 不使用代理 |
QNetworkProxy::DefaultProxy | 代理是根据使用setApplictionProxy设置的程序代理确定的 |
QNetworkProxy::Socks5Proxy | 使用Socks5代理(任何类型的连接的通用代理) |
QNetworkProxy::HttpProxy | 使用 HTTP 透明代理(使用“连接”命令实现,仅支持传出TCP连接;支持身份验证。) |
QNetworkProxy::HttpCachingProxy | 仅代理 HTTP 请求 |
QNetworkProxy::FtpCachingProxy | 仅代理 FTP 请求 |
客户端的建立过程:
- 创建一个QTcpSocke对象,QString 获取信息
- 使用connectToHost()来连接服务器端
- 如果有数据可用 会触发readyRead()
- 创建流,和设置版本号
- 使用bytesAvailable()函数来获取数据的大小
- 然后通过流读取数据
- 如果出现错误,Qt5.15 之前的版本使用SIGNAL(error(QAbstractSocket::SocketError)) Qt5.15版本之后使用errorOccured()
QTcpServer类:
QTcpServer可以接受传入的 TCP 连接。您可以指定端口或让 QTcpServer 自动选择一个端口。您可以侦听特定地址或所有计算机的地址。
函数:
listen(监听地址,端口号) | 告知服务器监听某个地址,可以指定端口号,如果端口号为0,则自动选择端口号 |
close() | 关闭服务器 |
errorString() | 返回上次发生的错误 |
isListening() | 是否在监听 |
maxPendingConnections() | 返回挂起的接受连接的最大数目。默认值为 30 |
nextPendingConnection() | 将下一个挂起的连接作为连接的 QTcpsocket 对象返回 |
pauseAccepting() | 暂停接受新连接。排队的连接将保留在队列中 |
resumeAccepting() | 恢复接受新连接. |
proxy() | 返回此套接字的网络代理,默认为QNetworkProxy::DefaultProxy |
serverAddress() | 如果服务器正在侦听连接,则返回服务器的地址; |
serverError() | 返回上次发生的错误的错误代码 |
serverPort() | 如果服务器正在侦听连接,则返回服务器的端口;否则返回 0。 |
setMaxPendingConnections(int) | 设置最大的挂起数,默认情况下,限制为 30 个挂起的连接 |
setProxy | 将此套接字的显式网络代理设置为网络代理 |
socketDescriptor() | 返回服务器用于侦听传入指令的本机套接字描述符,如果服务器未侦听,则返回 -1。 |
setSocketDescriptor() | 设置此服务器在侦听到套接字描述符的传入连接时应使用的套接字描述符 |
waitForNewConnection(int mesc=0,bool *timeout=nullptr) | 等待最多毫秒毫秒或直到传入连接可用。这是一个阻塞函数调用。不建议在单线程 GUI 应用程序中使用它,因为整个应用程序将停止响应,直到函数返回waitForNewConnection()。 在没有可用的事件循环时最有用。 非堵塞的替代方案是连接到newConnection()信号 |
信号:
acceptError() | 当接受新连接导致错误时,将发出此信号 |
newConnection() | 每次有新连接可用时都会发出此信号 |
使用的大致过程:
- 创建一个QTcpServer对象
- 使用listen()来监听传入的连接,每次客户端连接到服务器都会触发newConnection()信号
- 如果发生错误可以使用 serverError()返回错误的类型,也可以使用errorString()返回具体的描述
- 调用nextPendingConnection()接受挂起的连接作为连接的QTcpSocket
- 可以使用 serverAddress()返回正在监听的地址,serverPort()返回正在监听的端口
- 连接好后需要获取已经连接的套接字
- 然后使用QTcpSocket::wite()来发送数据
- 传输完后可以调用qQTcpSocket::disconnectFromHost()来关闭套接字
注意:QTcpServer主要设计用于事件循环,但也可以在没有事件循环的情况下使用,但必须使用waitForNewConnection(),用来阻止(堵塞),直到连接可用或超时到期。
简单的TCP简单的连接:
TCP服务器端的设计:
创建一个项目名为TCPserver
1.pro文件中添加 QT+=network
2.再.h文件中添加一个QTcpServer对象
3.在.cpp文件中添加一些配置
TCP客户端的配置:
创建一个新的项目名为 TCPclient
1.在.pro文件中添加QT+=network
2.在ui界面中添加以下控件
3. 在.h文件中添加一个QTcpSocket对象和一个QString quint16 对象
4.在.cpp中进行连接和读取数据
#include "client.h"
#include "ui_client.h"
#include<QMessageBox>
client::client(QWidget *parent)
: QWidget(parent)
, ui(new Ui::client)
{
ui->setupUi(this);
tcpsocket=new QTcpSocket(this);
connect(tcpsocket,&QTcpSocket::readyRead,this,[=]()//有新数据可用时
{
QDataStream in(tcpsocket);//创建流
in.setVersion(QDataStream::Qt_5_9);//设置版本号,客户端和服务器端的版本号要一致
if(size==0)//如果刚开始接收数据
{
//如果接收的数据小于两个字节,直接返回
if(tcpsocket->bytesAvailable()<(int)sizeof(quint16)) return;
in>>size;//大于两个字节的话保存到size中
}
//如果没有得到全部的数据,则返回继续接收数据
if(tcpsocket->bytesAvailable()<size)return;
in>>str;//将接收的数据存放到变量中
ui->lineEdit_3->setText(str);//显示数据
});
//如果出现错误,输出错误
connect(tcpsocket,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(displayError(QAbstractSocket::SocketError)));
}
client::~client()
{
delete ui;
}
void client::on_pushButton_clicked()//点击连接
{
size=0;//数据大小重置为0
tcpsocket->abort();//断开已有的连接
//连接lineEdit中的主机和端口号
tcpsocket->connectToHost(ui->lineEdit->text(),ui->lineEdit_2->text().toInt());
}
void client::displayError(QAbstractSocket::SocketError)//显示连接错误
{
QString S=tcpsocket->errorString();//错误信息
QMessageBox::information(this,"提示信息",S,QMessageBox::Ok);
}
运行结果:
由于是本地主机:可以输入localhost 或127.0.0.1 都可以运行
参考文献 :
使用Qt |进行网络编程Qt网络 5.15.12
QTcpServer 类 |Qt网络 5.15.12
QTcpSocket Class | Qt Network 5.15.12