注意:网络编程需要在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
#include
#include
#include
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
#include
#include
#include
#include
#include
#include
#include
#include
//#include
#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()< 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()< if(data_length==read_data.size()){ //数据是否接收完成。 // qDebug()< 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()< 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 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()< //按日返回 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()< //按周返回 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; } ```