注意:网络编程需要在pro文件里添加 network,如该用到qSqldatabase 需要添加sql
例:
QT+= network\
sql
#一、QTcpsocket:
QTcpsocet 是QT提供的tcp/ip的四层socket类.TCP(传输控制协议)是一种可靠的,面向流的,面向连接的传输协议。它特别适用于连续传输数据。
QTcpsocket 是QAbstractSocket的子类.
方法:
QTcpsocet::connectToHost(str 'ip', int port, QIODevice::ReadWrite) //连接socket
QTcpsocket::write(QBytearry) //数据的写入
虚构函数:
void QTcpsocket::readyRead() //实现接收到数据时执行
二、QTcpServer: socket _server
例子:
头文件
```
#ifndef TCP_SERVER_H
#define TCP_SERVER_H
#include <QTcpServer>
#include <QTcpSocket>
#include <QJsonObject>
#include <QObject>
class tcp_server : public QTcpServer //重写QTcpServer
{
Q_OBJECT
public:
tcp_server(); //构造函数
QByteArray data_length_data(QByteArray data); //用于对要发送的数据头部添加包长度。
protected:
void incomingConnection(qintptr soketnember); //有新连接时执行,创造socket连接。
signals:
public slots:
// void socket_write(QJsonObject user_passwd,QTcpSocket *tcpsocket);
};
class tcp_socket : public QTcpSocket //重写tcpsocket
{
Q_OBJECT
public:
tcp_socket(qintptr soketDescriptor, QTcpSocket *parent=NULL); // soketDescriptor socket号。
void router(); //接收数据路由。
QByteArray data_length_data(QByteArray data); //对发送的数据添加包长度
private:
int m_tcpBlockSize = 0; //数据包长度计算
bool is_one; //是否是第一个数据包
int data_length; //数据包长度
QByteArray read_data; //数据包缓存(在接收到的数据包未达到第一个包描述的大小时缓存用)
//sql db;
signals:
void return_db(QJsonObject user_passwd,QTcpSocket *tcpsocket); //查询数据库信号,qsqldatabase 的多线程问题,所有发送信号到主进程。
private slots:
void Read_data(); //有数据进来时调用
};
#endif // TCP_SERVER_H
'''
.cpp部分:
#include "tcp_server.h"
#include <QTcpServer>
#include <QThread>
#include <QDebug>
#include <QString>
#include <QDataStream>
#include <QJsonObject>
#include <QJsonArray>
#include <QByteArray>
#include <QJsonDocument>
//#include <QJsonObject>
#include "sql.h" //数据库查询,写入部分,于本笔记无关可忽略
#include "cache.h" //全局变量,用于缓存最后一次的值,于本笔记无关,可忽略
tcp_server::tcp_server()
{
}
void tcp_server::incomingConnection(qintptr soketnember){ //有新连接时执行
tcp_socket * socket=new tcp_socket(soketnember); //创建一个socket连接指针并按“本机套接字描述符”创建
QThread *task=new QThread(); 创建一个线程地址。
connect(socket,SIGNAL(disconnected()),task,SLOT(quit())); //socket断开连接时退出线程
connect(socket,SIGNAL(readyRead()),socket,SLOT(Read_data())); //有数据传入时执行Read_data()槽
connect(socket,SIGNAL(return_db(QJsonObject,QTcpSocket*)),this,SLOT(socket_write(QJsonObject,QTcpSocket*))); //用于解决QSqldatabase 多线程问题,在需要查询数据库时发送给主进程执行,由主进程直接返回给客户端的socket 。
socket->moveToThread(task); //移动socket 到线程
task->start(); //线程启动
}
void tcp_server::socket_write(QJsonObject user_password,QTcpSocket *tcpsocket){
sql db; //初始化数据库类,此类为自定义类,与本笔记无关
qDebug()<<user_password;
QString user=user_password.value("user").toString();
QString password=user_password.value("password").toString();
QJsonObject login_status=db.login(user,password);
QJsonObject data_send;
data_send.insert("type","login");
data_send.insert("data",login_status);
tcpsocket->write(data_length_data(QJsonDocument(data_send).toJson())); //socket 直接返回给客户端
tcpsocket->waitForBytesWritten(1000); //写超时设定为1秒。
}
tcp_socket::tcp_socket(qintptr soketDescriptor, QTcpSocket *parent) :QTcpSocket(parent)
{
this->setSocketDescriptor(soketDescriptor); //设置这个连接的描述符是由QTcpserver传入的连接描述符。
}
void tcp_socket::Read_data(){ //读取数据
if(m_tcpBlockSize==0){ //判断已接收的数据是否为0,0表示第一个数据包。
QByteArray dd=this->readAll(); //读出所有数据。
QDataStream cc(&dd,QIODevice::ReadWrite); //以流数据方式打开
cc.device()->seek(0); //设置数据指针为0.
cc>>data_length; //获取数据包大小。所以要求客户段传来的数据包前4个byte时int的包大小。
if(!data_length>8){
this->disconnect();
this->close();
}
// 包描述: qbytearry [int(包大小),xxxxxxxxxxxxxxxxxxxxxxx.......数据部分]
cc.device()->seek(sizeof(int)); //移动指针到包大小描述后的数据开始位。
while (!cc.atEnd()) { //循环判断数据是否读取到结尾
unsigned char tmp_char;
cc>>tmp_char;
read_data.append(tmp_char); //把每个byte追加到缓存中。
}
// qDebug()<<data_length<<read_data.size();
if(data_length==read_data.size()){ //数据是否接收完成。
// qDebug()<<read_data;
router(); //完成时调用路由
}
m_tcpBlockSize=1; //设置为1表示后面的包不在是第一个数据包
cc.device()->close();
}else { //不是第一个包时执行
QByteArray dd=this->readAll();
QDataStream cc(&dd,QIODevice::ReadWrite);
while (!cc.atEnd()) {
unsigned char tmp_char;
cc>>tmp_char;
read_data.append(tmp_char);
}
if(data_length==read_data.size()){
router();
}
cc.device()->close();
}
}
void tcp_socket::router(){ //路由部分
if(QJsonDocument::fromJson(read_data).isObject()){
// qDebug()<<read_data;
QJsonObject data=QJsonDocument::fromJson(read_data).object();
if(data.keys().contains("type")){
QString type=data.value("type").toString();
if(type=="last_temperatuer"){
//返回最后一次温度
QJsonObject data_send;
data_send.insert("type","last_temperatuer");
data_send.insert("data",last_temperatuer);
QByteArray byte_data=QJsonDocument(data_send).toJson();
this->write(data_length_data(byte_data));
}else if(type=="last_wendu_collector"){
// insert 返回最后一次温度
QJsonArray tmp_arry;
QJsonObject send_data=data.value("data").toObject();
last_temperatuer=tmp_arry;
for(int i=0;i<send_data.keys().length();i++){
QString key=send_data.keys()[i];
QJsonObject tmp_data;
tmp_data.insert(key,send_data.value(key).toInt());
last_temperatuer.append(tmp_data);
}
}
else if (type=="temperatuer_day_hour") {
int day=data.value("day").toInt();
QString temperatuer_type=data.value("temperatuer_type").toString();
QJsonArray data_list=db.day_hour_temperatuer(day,temperatuer_type);
QJsonObject data_send;
data_send.insert("type","temperatuer_day_hour");
data_send.insert("data",data_list);
QByteArray byte_data=QJsonDocument(data_send).toJson();
this->write(data_length_data(byte_data));
}else if (type=="temperatuer_ri") {
//按日返回
QString temperatuer_type=data.value("temperatuer_type").toString();
QJsonArray data_list=db.temperatuer_ri(temperatuer_type);
QJsonObject data_send;
data_send.insert("type","temperatuer_ri");
data_send.insert("data",data_list);
QByteArray byte_data=QJsonDocument(data_send).toJson();
this->write(data_length_data(byte_data));
}else if (type=="temperatuer_yue") {
// qDebug()<<type;
//按日返回
QString temperatuer_type=data.value("temperatuer_type").toString();
// sql db;
QJsonArray data_list=db.temperatuer_yue(temperatuer_type);
QJsonObject data_send;
data_send.insert("type","temperatuer_yue");
data_send.insert("data",data_list);
QByteArray byte_data=QJsonDocument(data_send).toJson();
this->write(data_length_data(byte_data));
}else if (type=="temperatuer_zhou") {
// qDebug()<<type;
//按周返回
QString temperatuer_type=data.value("temperatuer_type").toString();
QJsonArray data_list=db.temperatuer_zhou(temperatuer_type);
QJsonObject data_send;
data_send.insert("type","temperatuer_zhou");
data_send.insert("data",data_list);
QByteArray byte_data=QJsonDocument(data_send).toJson();
this->write(data_length_data(byte_data));
}else if (type=="temperatuer_yue") {
//按月返回
QString temperatuer_type=data.value("temperatuer_type").toString();
QJsonArray data_list=db.temperatuer_yue(temperatuer_type);
QJsonObject data_send;
data_send.insert("type","temperatuer_yue");
data_send.insert("data",data_list);
QByteArray byte_data=QJsonDocument(data_send).toJson();
this->write(data_length_data(byte_data));
}else if (type=="login") {
return_db(data,this);
}else if (type=="on_off") {
QString user=data.value("user").toString();
int value=data.value("value").toInt();
QJsonObject on_off_status=db.set_action(user,type,value);
QJsonObject data_send;
data_send.insert("type","on_off");
data_send.insert("data",on_off_status);
this->write(data_length_data(QJsonDocument(data_send).toJson()));
}else if (type=="set_moshi_leng_re") {
QString user=data.value("user").toString();
int value=data.value("value").toInt();
QJsonObject moshi_leng_re=db.set_action(user,type,value);
QJsonObject data_send;
data_send.insert("type","set_moshi_leng_re");
data_send.insert("data",moshi_leng_re);
this->write(data_length_data(QJsonDocument(data_send).toJson()));
}
}else {
this->disconnect();
this->close();
}
}else {
this->disconnect();
this->close();
}
}
QByteArray tcp_socket::data_length_data(QByteArray data){
QByteArray send_data;
QDataStream bin_data(&send_data,QIODevice::ReadWrite);
int data_length=data.size();
bin_data<<(int)data_length;
send_data.append(data);
return send_data;
}
QByteArray tcp_server::data_length_data(QByteArray data){
QByteArray send_data;
QDataStream bin_data(&send_data,QIODevice::ReadWrite);
int data_length=data.size();
bin_data<<(int)data_length;
send_data.append(data);
return send_data;
}
```