淘宝优惠劵网站建设,个人网站名称请,微网站如何做微信支付宝支付宝,个人备案网站建设方案书目录
前言
一、UDP网络编程
1.Qt项目文件
2.UDP类
QUdpSocket
QNetworkDatagram
3.UDP回显服务器案例
细节
服务器设计
客户端设计
二、TCP网络编程
1.TCP类
QTcpServer
QTcpSocket
2.TCP回显服务器案例
细节
服务器设计
客户端设计
三、HTTP客户端
1.HTTP…目录
前言
一、UDP网络编程
1.Qt项目文件
2.UDP类
QUdpSocket
QNetworkDatagram
3.UDP回显服务器案例
细节
服务器设计
客户端设计
二、TCP网络编程
1.TCP类
QTcpServer
QTcpSocket
2.TCP回显服务器案例
细节
服务器设计
客户端设计
三、HTTP客户端
1.HTTP客户端类
QNetworkAccessManager
QNetworkRequest
QNetworkReply
2.HTTP客户端案例 前言 我们之前学习的系统相关的内容在不同的系统下的理论和实现可能都不太一样但是对于计算机网络模块来说因为网络提供了不同主机之间的信息通信那么如何想让两个主机进行通信那么他们的通信模块也就是计算机模块的实现也就必须是一样的才可以。所以说计算机网络模块的实现对于不同的系统也是一样的最主要的区别就是在于语言层面上对于网络编程的系统接口的封装。对于C标准库中一直是没有提供网络编程相关的API库。 在整个网络协议栈来看网络编程就是我们对于用户层的一种编写但是我们想要传输数据的时候需要传输层协议的支持但是传输层协议有两个所以我们在应用层也需要采用一些接口去指定传输层协议。 一、UDP网络编程
1.Qt项目文件 .pro文件是 Qt 项目文件。它是一个文本文件包含了项目的各种信息和配置用于指导qmake如何构建 Qt 项目。所以在Qt中进行网络编程之前需要在项目当中的.pro文件中添加network模块来引入网络编程模块。在我们之前使用的所有控件都是包含在QtCore模块当中的只不过默认生成.pro文件的时候就已经添加了。而且Qt来提供了很多其他的模块。 Qt为什么要划分出这么多模块呢因为Qt本身是一个非常大的框架如果我们默认把所有Qt提高的功能模块全都一下引入项目当中那么即使我们写一个简单的打印helloworld那么生成的可执行程序也会 非常的大可执行程序内部编译了许多用不到的内容。所以为了让生成的Qt项目更加的轻量化那么就把不同的功能划分成了多个模块我们需要使用的时候就需要在.pro文件中引入包含了。 而且为了让多模块的项目更加的轻量化Qt也提高了模块的动态库和静态库的两种版本。 2.UDP类 Qt对于UDP的类有两个一个是QUdpSocket表示udp通信套接字文件类另一个是表示一个UDP数据报的类QNetworkDatagram类。
QUdpSocket
名称说明 bind(const QHostAddress, quint16) 绑定指定的端口号receiveDatagram()返回一个UDP数据报对象writeDatagram(const QNetworkDatagram)发送一个UDP数据报readyRead信号在收到数据并准备就绪后触发
对于读取数据的操作在C语言层面的接口或者系统的底层原生接口默认都是阻塞方式的等待当然也可以设置非阻塞而Qt在处理读取数据操作的时候并不是阻塞或者非阻塞等待的方式而是采用信号槽机制当有数据到来并就绪只会就会发送readRead信号。QHostAddress是一个用于表示IP地址的一个类对于服务器来说设置为QHostAddress::Any即可表示可以用于监听任何地址的连接对于IPv4和IPv6都适用。对于bind函数可能会绑定失败但是他会将失败的原因存放起来可以通过errorString成员函数获取到失败信息。
QNetworkDatagram
名称说明QNetworkDatagram(const QByteArray const HostAddress, quint16)构造函数通过QByteArray目标ip和端口号构造一个UDP数据报data()获取数据报内部持有的数据返回一个QByteArray类型对象senderAddress()获取数据报中包含的对端ip地址senderPort()获取数据报中包含的对端端口号 3.UDP回显服务器案例 只是一个使用网络接口的案例因为一般来说服务器都不会带有图形化界面的。
细节
在readyRead信号绑定槽函数和bind操作的顺序来说要先绑定信号槽后bind因为一旦绑定ip和端口号之后就可能会有通信数据到来了。那么在进行信号槽的绑定就会来不及了早到的数据就因为没有槽函数所以不进行处理了。我们下面的服务器设计中带有了图形化界面在配置文件.pro文件中也可以看到我们引入了gui模块那么我们的云服务器默认是没有装配图形化界面的所以是没有办法直接将我们下面写的服务器端代码放入到云服务器允许的。而对于我们现在写的Qt的udp客户端是可以直接连接linux服务器下的udp服务器的。所以说网络底层协议的实现都是一样的。udp都是一套逻辑。一般Qt都不会写服务器大多数都是写客户端然后用Qt客户端连接linux服务器。
服务器设计
widget.h文件
class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent nullptr);~Widget();QString porcess(const QString request);public slots:void processRequest();private:Ui::Widget *ui;//引入Udp成员QUdpSocket* socket;
};
widget.cpp文件
#include widget.h
#include ui_widget.h
#include QMessageBox
#include QNetworkDatagramWidget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui-setupUi(this);//创建udp对象socket new QUdpSocket(this);//设置窗口标题this-setWindowTitle(服务器);//连接信号槽connect(socket, QUdpSocket::readyRead, this, Widget::processRequest);//绑定端口号bool retbind socket-bind(QHostAddress::Any, 8082);if(retbind false){QMessageBox::critical(this, 服务器启动出错, socket-errorString());return;}}Widget::~Widget()
{delete ui;
}//但是我们这里是回显所以没有什么处理过程
QString Widget::porcess(const QString request)
{return request;
}void Widget::processRequest()
{//获取请求信息const QNetworkDatagram udp_request socket-receiveDatagram();//转化为字符串类型QString data_request udp_request.data();//处理请求const QString data porcess(data_request);//构建相应数据报QNetworkDatagram response(data.toUtf8(), udp_request.senderAddress(), udp_request.senderPort());//发送回客户端socket-writeDatagram(response);//把客户端发的信息显示到listWidget控件上QString log [ udp_request.senderAddress().toString() : QString::number(udp_request.senderPort()) ] message: data_request;ui-listWidget-addItem(log);
}
客户端设计 widget.h文件
class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent nullptr);~Widget();private slots:void on_pushButton_clicked();private:Ui::Widget *ui;//引入udp对象QUdpSocket* socket;
};
widget.cpp文件
#include widget.h
#include ui_widget.h
#include QNetworkDatagramWidget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui-setupUi(this);//设置窗口名称this-setWindowTitle(客户端);//创建udp对象socket new QUdpSocket(this);//连接信号槽connect(socket, QUdpSocket::readyRead, this, [](){//获取数据报const QNetworkDatagram udp_response socket-receiveDatagram();//读取数据const QString data udp_response.data();//写入对话框中ui-listWidget-addItem(服务器 data);});
}Widget::~Widget()
{delete ui;
}
//发送按钮
void Widget::on_pushButton_clicked()
{//获取输入框的内容const QString text ui-lineEdit-text();//构建请求数据报const QString ip 127.0.0.1;const quint16 port 8082;QNetworkDatagram data_request(text.toUtf8(), QHostAddress(ip), port);//发送数据socket-writeDatagram(data_request);//更新对话框中的内容ui-listWidget-addItem(客户端 text);//情况输入框ui-lineEdit-clear();
}二、TCP网络编程
1.TCP类 Qt对于TCP的类提供两个第一个是QTcpServer用于监听端口实现获取客户端连接的操作相当于是listensocket以及对于bind、listen以及accept接口函数的一个封装。第二个是用于客户端和服务器之间数据交互的类QTcpSocket类。
QTcpServer
名称说明listen(const QHostAddress, quint16 port)绑定ip和端口号并开始监听相当于bind和listen的结合nextPendingConnection()从系统当中获取到一个已经建立好的tcp连接返回一个QTcpSocket对象通过这个对象是实现与客户端之间的通信newConnection信号有新的客户端建立连接完毕之后触发的信号
QTcpSocket
名称说明readAll()读取当前接收缓冲区中的所有数据返回QByteArray对象write(const QByteArray)把输入写入到socket的发送缓冲区中deleteLater()暂时把socket对象标记为无效Qt会在下个事件循环中析构释放该对象、peerAddress()获取对端ip地址peerPort()获取对端端口号 connectToHost( const QString hostName, quint16 port) 向服务器发起连接readyRead信号有数据到来并准备就绪触发disconnected信号连接断开的时候触发 2.TCP回显服务器案例
细节
对于客户端向服务器发起连接的connectToHost函数返回值为void类型但是我们还是要判断是否连接成功了所以QTcpSocket类中提供了waitForConnected函数该函数的作用是让当前线程处理等待状态直到连接成功或者连接反馈错误为止又或者说超时。
服务器设计
widget.h文件
class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent nullptr);~Widget();public slots:void processConnection();private:Ui::Widget *ui;//引入Tcp对象QTcpServer* socket;
};
widget.cpp文件
#include widget.h
#include ui_widget.h
#include QMessageBoxWidget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui-setupUi(this);//设置窗口标题this-setWindowTitle(服务器);//tcp对象实例化socket new QTcpServer(this);//绑定newConnection的信号槽函数connect(socket, QTcpServer::newConnection, this, Widget::processConnection);//进行bind和listen操作bool retlisten socket-listen(QHostAddress::Any, 8082);if(retlisten false){QMessageBox::critical(this, 服务器启动失败, socket-errorString());return;}
}Widget::~Widget()
{delete ui;
}//获取新连接的信号处理函数
void Widget::processConnection()
{//获取新连接QTcpSocket* client socket-nextPendingConnection();//构建日志QString log [ client-peerAddress().toString() : QString::number(client-peerPort()) ] 新客户端上线;ui-listWidget-addItem(log);//通过信号槽触发接收消息connect(client, QTcpSocket::readyRead, this, [](){//读取消息QString message client-readAll();//处理消息--此处没有处理只是回显//写回到客户端client-write(message.toUtf8());//构建日志QString log [ client-peerAddress().toString() : QString::number(client-peerPort()) ] say: message;//写到界面ui-listWidget-addItem(log);});//处理断开连接的信号槽函数connect(client, QTcpSocket::disconnected, this, [](){//构建日志QString log [ client-peerAddress().toString() : QString::number(client-peerPort()) ] 客户端下线;//释放对象client-deleteLater();});
}
客户端设计
widget.h文件
class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent nullptr);~Widget();private slots:void on_pushButton_clicked();private:Ui::Widget *ui;//构建tcp对象QTcpSocket* socket;
};
widget.cpp文件
#include widget.h
#include ui_widget.h
#include QMessageBoxWidget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui-setupUi(this);//设置窗口标题this-setWindowTitle(客户端 );//实例化tcp对象socket new QTcpSocket(this);//向服务器发起连接socket-connectToHost(127.0.0.1, 8082);//确认是否连接成功if(!socket-waitForConnected()){QMessageBox::critical(this, 连接服务器出错, socket-errorString());return;}//绑定接收到消息的信号槽函数connect(socket, QTcpSocket::readyRead, this, [](){//获取接收到的内容QString message socket-readAll();//将内容打印到对话框中QString log 服务器: message;ui-listWidget-addItem(log);});
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_clicked()
{//获取输入框的内容QString message ui-lineEdit-text();//将内容发送给服务器socket-write(message.toUtf8());//将内容打印到对话框中ui-listWidget-addItem(客户端: message);//情况输入框ui-lineEdit-clear();
} 三、HTTP客户端
1.HTTP客户端类 Qt中为HTTP协议的客户端主要提供了三个类一个是QNetworkAccessManager类该类提供了HTTP有关的核心操作。第二个类是QNetworkRequest类表示一个不含body的HTTP请求。第三个类就是QNetworkReply类表示一个HTTP的响应。 上述也说了真正的服务器一定也不会使用Qt就实现所以Qt就没有提供服务端相关的HTTP类。
QNetworkAccessManager
方法说明get(const QNetworkRequest)发起一个HTTP GET请求返回一个QNetworkReply对象post(const QNetworkRequest, const QByteArray)发起一个HTTP POST请求也返回一个QNetworkReply对象
QNetworkRequest 一个HTTP协议的完整报文应该是包括报头和有效载荷的而这个类只是实现了一个报头对于有效载荷该类不进行实现而且对于请求报文来说一般都不会带有一些实质性的内容只会传递一些kv形式的参数内容通过post方法来传递所以post方法也为我们提供了传递kv的参数。
方法说明QNetworkRequest(const QUrl)通过Url构造一个HTTP请求setHeader(QNetworkRequest::knownHeaders header, const QVariant value)设置请求头部字段 对于报头的请求行字段Qt也进行了一定的封装方便我们去设置请求行Qt中采用的是枚举类型将常用的请求行字段进行一一列举出来QNetworkRequest::knownHeaders就是该枚举对象。 对于QVariant类对象表示一个类型可变的值。
QNetworkReply
方法说明error()获取出错状态errorString()获取出错原因的字符串描述readAll()获取响应的body字段header(QNetworkRequest::knownHeaders header)获取响应头部字段finished信号当客户端收到一个完整的响应报文只会触发 2.HTTP客户端案例
细节
如何想要显示出来元素的HTML报文那么就不可以使用QTextEdit控件因为他会对HTML代码进行渲染显示出来的就不是原始的HTML报文了所以需要使用QPlainTextEidt控件。对于get、post等系列函数只是负责发送请求不负责请求的等待所以说他返回的响应对象是一个没有实际内容的对象那什么时候才收到响应呢依靠的是finished信号通过信号槽机制去处理finished信号也就相当于处理响应了。
#include widget.h
#include ui_widget.h
#include QNetworkReplyWidget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui-setupUi(this);//实例化manager new QNetworkAccessManager(this);
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_clicked()
{//获取到输入框中的url并构建一个url对象QUrl url(ui-lineEdit-text());//构造一个http请求对象QNetworkRequest request(url);//发送get请求返回一个响应QNetworkReply* response manager-get(request);//信号槽connect(response, QNetworkReply::finished, this, [](){//正确响应了if(response-error() QNetworkReply::NoError){QString html_data response-readAll();ui-plainTextEdit-setPlainText(html_data);}else{ui-plainTextEdit-setPlainText(response-errorString());}//释放response对象response-deleteLater();});
}