​下载地址:https://pan.baidu.com/s/1UuQKQzebcwhkq2fdPE6Q3A​​ 提取码:s117


1、新建一个QT项目,在.pro文件中导入网络模块包


QT       +=

界面布局如下:

QT--TCP服务器搭建_物联网


QT--TCP服务器搭建_#include_02

2、我们新建一个TcpServer 类,继承自QTcpServer

tcpserver.h


#ifndef TCPSERVER_H
#define TCPSERVER_H

#include <QTcpServer>
#include "tcpsocket.h"
#include <QThread>

class TcpServer : public QTcpServer
{
Q_OBJECT
public:
TcpServer(QObject *parent = 0);

QMap<int,TcpSocket*> IDSocketMap;
QMap<int,QString> IDUserMap;
int serverSocketCount=0;//用于统计连接的用户数


protected:
void incomingConnection(qintptr serverSocketID);

signals:
void sig_hasData(qintptr serverSocketID,QString IP,int Port,QByteArray data);
void sig_hasConnect(qintptr serverSocketID,QString IP,int Port);
void sig_hasDisConnect(qintptr serverSocketID,QString IP,int Port);
void sig_ListSocket(QMap<int,TcpSocket*> idSocketMap,QMap<int,QString> idUserMap);


private slots:
void slot_ReadData(qintptr serverSocketID,QString IP,int Port,QByteArray data);//连接到ServerSocket的void serverSocketReadData……信号
void slot_DisConnect(qintptr serverSocketID,QString IP,int Port);

};

#endif // TCPSERVER_H

tcpserver.cpp


#include "tcpserver.h"

TcpServer::TcpServer(QObject *parent) : QTcpServer(parent)
{

}

//复写函数incomingConnection(qintptr serverSocketID)
void TcpServer::incomingConnection(qintptr serverSocketID)
{
QThread* thread = new QThread;
TcpSocket *serverSocket=new TcpSocket(this,serverSocketID);
serverSocket->setSocketDescriptor(serverSocketID);

connect(serverSocket,SIGNAL(sig_SocketReadData(qintptr,QString,int,QByteArray)),
this,SLOT(slot_ReadData(qintptr,QString,int,QByteArray)));
connect(serverSocket,SIGNAL(sig_SocketDisConnect(qintptr,QString,int)),
this,SLOT(slot_DisConnect(qintptr,QString,int)));
connect(serverSocket,SIGNAL(aboutToClose()),
this,SLOT(deleteLater()));//关闭监听时,对象自动删除

IDSocketMap.insert(serverSocketID,serverSocket);
serverSocketCount++;

serverSocket->moveToThread(thread);
thread->start();

emit sig_hasConnect(serverSocketID, serverSocket->peerAddress().toString(),serverSocket->peerPort());
emit sig_ListSocket(IDSocketMap,IDUserMap);
}

void TcpServer::slot_ReadData(qintptr serverSocketID,QString IP,int Port,QByteArray data)
{
emit sig_hasData(serverSocketID,IP,Port,data);
}

void TcpServer::slot_DisConnect(qintptr serverSocketID,QString IP,int Port)
{
IDSocketMap.remove(serverSocketID);
IDUserMap.remove(serverSocketID);
serverSocketCount--;
emit sig_hasDisConnect(serverSocketID,IP,Port);
}

3、我们新建一个tcpsocket类,继承自QTcpSocket

tcpsocket.h


#ifndef TCPSOCKET_H
#define TCPSOCKET_H

#include <QTcpSocket>
#include <QHostAddress>
#include <QAbstractSocket>

class TcpSocket : public QTcpSocket
{
Q_OBJECT
public:
TcpSocket(QObject *parent = 0,int serverSocketID=0);

signals:
void sig_SocketReadData(qintptr serverSocketID,QString IP,int Port,QByteArray data);
void sig_SocketDisConnect(qintptr serverSocketID,QString IP,int Port);

private:
int serverSocketID;

private slots:
void ReadData();//具体实现读取数据
void DisConnect();
void outPutError(QAbstractSocket::SocketError);//qDebug输出套接字出错信息
};

#endif // TCPSOCKET_H

tcpsocket.cpp


#include "tcpsocket.h"

TcpSocket::TcpSocket(QObject *parent,int serverSocketID) : QTcpSocket(parent)
{
this->serverSocketID=serverSocketID;
connect(this,SIGNAL(readyRead()),this,SLOT(ReadData()));//挂接读取数据信号
connect(this,SIGNAL(disconnected()),this,SLOT(DisConnect()));//关闭连接时,发送断开连接信号
connect(this,SIGNAL(disconnected()),this,SLOT(deleteLater()));//关闭连接时,对象自动删除

connect(this,SIGNAL(error(QAbstractSocket::SocketError)),
this,SLOT(outPutError(QAbstractSocket::SocketError)));

}
void TcpSocket::ReadData()
{
//读取完整一条数据并发送信号
QByteArray data=this->readAll();
emit sig_SocketReadData(this->serverSocketID,this->peerAddress().toString(),this->peerPort(),data);
}

void TcpSocket::DisConnect()
{
//断开连接时,发送断开信号
emit sig_SocketDisConnect(this->serverSocketID,this->peerAddress().toString(),this->peerPort());
}

void TcpSocket::outPutError(QAbstractSocket::SocketError)
{
this->disconnectFromHost();
qDebug()<< this->errorString();
}

4、我们在主类中使用自定义的两个类

mainwindow.h


#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "tcpserver.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();

void judge_order(qintptr serverSocketID,QString IP,int Port,QString data); //指令分析
void BroadCast(QString msg); //广播信息


private:
Ui::MainWindow *ui;
TcpServer *Server;
QTcpSocket *tcpSocket;

signals:


public slots:
void slot_updateCount(); //更新在线数
void slot_updateData(qintptr serverSocketID,QString IP,int Port,QByteArray data); //收到数据

private slots:
void on_pushButton_open_clicked();
void on_pushButton_close_clicked();
void on_pushButton_clear_clicked();
};
#endif // MAINWINDOW_H

mainwindow.cpp


#include "mainwindow.h"
#include "ui_mainwindow.h"

QByteArray data_all = NULL;

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);

Server = new TcpServer(this);
tcpSocket = new QTcpSocket;

//连接、断开更新在线数
connect(Server,SIGNAL(sig_hasConnect(qintptr,QString,int)),this,SLOT(slot_updateCount()));
connect(Server,SIGNAL(sig_hasDisConnect(qintptr,QString,int)),this,SLOT(slot_updateCount()));

//有数据
connect(Server,SIGNAL(sig_hasData(qintptr,QString,int,QByteArray)),
this,SLOT(slot_updateData(qintptr,QString,int,QByteArray)));
}

MainWindow::~MainWindow()
{
delete ui;
}
//=============更新在线数===============================================================
void MainWindow::slot_updateCount()
{
ui->label_num->setText(QString::number(Server->serverSocketCount));
}
//=============接收数据===============================================================
void MainWindow::slot_updateData(qintptr serverSocketID,QString IP,int Port,QByteArray data)
{
QString DATA=data;
QString str=QString("从 socket: %1 ip: %2 port: %3 收到\n->: %4").arg(serverSocketID).arg(IP).arg(Port).arg(DATA);
ui->plainTextEdit_show->appendPlainText(str);

if(DATA.startsWith('@')&&DATA.endsWith('#'))//judge if order
{
judge_order(serverSocketID,IP,Port,DATA);
}//judge if order
}
//============指令分析================================================================
void MainWindow::judge_order(qintptr serverSocketID,QString IP,int Port,QString order)
{
QByteArray change = order.toUtf8();
data_all=change;

QString ORDER=order.mid(1,order.length()-2);
QStringList List=ORDER.split(";");

//@data;001;0# 编号001的结点,关闭
if(List[0]==QString::fromLocal8Bit("data"))
{
//广播指令
BroadCast(QString("@command;%1;%2#").arg(List[1]).arg(List[2]));
}
//@HBIT;001# 编号001的结点,心跳
if(List[0]==QString::fromLocal8Bit("HBIT"))
{
//回复心跳
QByteArray command = QString("@HBIT;%1#").arg(List[1]).toUtf8();
tcpSocket->setSocketDescriptor(serverSocketID);
tcpSocket->write(command);
}
}
//============广播信息=========================================================
void MainWindow::BroadCast(QString msg)
{
QByteArray Broadcast;
Broadcast = msg.toUtf8();
QMap <int,TcpSocket *>::const_iterator Device;
for(Device=Server->IDSocketMap.constBegin();Device!=Server->IDSocketMap.constEnd();++Device)
{
Device.value()->write(Broadcast);
}
}
//=====================================================================

void MainWindow::on_pushButton_open_clicked() //启动服务器
{
ui->pushButton_open->setEnabled(false);
ui->pushButton_close->setEnabled(true);
int Port = 6666;
Server->listen(QHostAddress::Any,Port);//监听客户端连接
ui->label_IP->setText("47.101.217.158");
ui->label_Port->setText(QString::number(Port));
ui->label_status->setText("运行中!");
}

void MainWindow::on_pushButton_close_clicked() //关闭服务器
{
Server->close();
ui->pushButton_close->setEnabled(false);
ui->pushButton_open->setEnabled(true);
ui->label_status->setText("关闭!");
ui->label_IP->setText("");
ui->label_Port->setText("");
ui->label_num->setText("0");
ui->plainTextEdit_show->clear();
}

void MainWindow::on_pushButton_clear_clicked() //清空信息栏
{
ui->plainTextEdit_show->clear();
}