QT--TCP服务器搭建

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


QT       += network

界面布局如下:
在这里插入图片描述
在这里插入图片描述

2、我们新建一个serversocket类,继承自QTcpSocket

serversocket.h


#ifndef SERVERSOCKET_H
#define SERVERSOCKET_H

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

class ServerSocket : public QTcpSocket
{
    Q_OBJECT
public:
    explicit ServerSocket(QObject *parent = 0,int serverSocketID=0);//在这里为它多加了serverSocketID,将TcpServer的SocketDescriptor传进来。
signals:
    void serverSocketReadData(qintptr serverSocketID,QString IP,int Port,QByteArray data);//自建的server类,通过这个信号,得到传输来的数据的来源及具体内容
    void serverSocketDisConnect(qintptr serverSocketID,QString IP,int Port);//断开连接时,通过这个信号,Server类将容器idSocketMap内对应的套接字删除
private:
    int serverSocketID;
private slots:
    void ReadData();//具体实现读取数据
    void DisConnect();
    void outPutError(QAbstractSocket::SocketError);//qDebug输出套接字出错信息


};

#endif // SERVERSOCKET_H

serversocket.cpp


#include "serversocket.h"


ServerSocket::ServerSocket(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 ServerSocket::ReadData()
{
    //读取完整一条数据并发送信号
    QByteArray data=this->readAll();
    emit serverSocketReadData(this->serverSocketID,this->peerAddress().toString(),this->peerPort(),data);
}

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

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

3、我们新建一个server类

server.h


#ifndef SERVER_H
#define SERVER_H
#include "serversocket.h"
#include <QTcpServer>
#include <QMap>


class Server : public QTcpServer
{
    Q_OBJECT
public:
    explicit Server(QObject *parent = 0);
    int serverSocketCount=0;//用于统计连接的用户数,
public:
    QMap<int,ServerSocket *> idSocketMap;
    QMap<int,QString> idUserMap;


protected:
    void incomingConnection(qintptr serverSocketID);

signals:
    void hasData(qintptr serverSocketID,QString IP,int Port,QByteArray data);//这三个信号用于告诉dialog信息,用于dialog的UI的信息显示,比如更新显示用户连接数
    void hasConnect(qintptr serverSocketID,QString IP,int Port);
    void hasDisConnect(qintptr serverSocketID,QString IP,int Port);
    void ListSocket(QMap<int,ServerSocket *> idSocketMap,QMap<int,QString> idUserMap);


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


};

#endif // SERVER_H

server.cpp


#include "server.h"
#include "serversocket.h"
#include <QDebug>
#include <dialog.h>
Server::Server(QObject *parent) :
    QTcpServer(parent)
{

}
//复写函数incomingConnection(qintptr serverSocketID)
void Server::incomingConnection(qintptr serverSocketID)
{
    ServerSocket *serverSocket=new ServerSocket(this,serverSocketID);
    serverSocket->setSocketDescriptor(serverSocketID);

    connect(serverSocket,SIGNAL(serverSocketReadData(qintptr,QString,int,QByteArray)),
            this,SLOT(ReadData(qintptr,QString,int,QByteArray)));
    connect(serverSocket,SIGNAL(serverSocketDisConnect(qintptr,QString,int)),
            this,SLOT(DisConnect(qintptr,QString,int)));
    connect(serverSocket,SIGNAL(aboutToClose()),
            this,SLOT(deleteLater()));//关闭监听时,对象自动删除

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


    emit hasConnect(serverSocketID, serverSocket->peerAddress().toString(),serverSocket->peerPort());
    emit ListSocket(idSocketMap,idUserMap);
}

void Server::ReadData(qintptr serverSocketID,QString IP,int Port,QByteArray data)
{
    emit hasData(serverSocketID,IP,Port,data);
}

void Server::DisConnect(qintptr serverSocketID,QString IP,int Port)
{
    idSocketMap.remove(serverSocketID);
    idUserMap.remove(serverSocketID);
    serverSocketCount--;
    emit hasDisConnect(serverSocketID,IP,Port);
}

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

dialog.h


#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include "server.h"
#include <QTcpSocket>
#include <QMessageBox>
#include <QString>
#include <QStringList>
#include <string>
#include <QFile>
#include <QFileDevice>
#include <QIODevice>
#include <QTextStream>
#include <QMapIterator>
#include <string>


namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT
public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();
    QMap<int,ServerSocket *> ids;
    QString read_ip_address();

private:
    Ui::Dialog *ui;
    Server *myserver;
    QTcpSocket *tcpSocket;
    QTcpSocket *tcpSocket1;
    QTcpSocket *tcpSocket2;

signals:  
    void has_order(qintptr serverSocketID,QString IP,int Port,QString order);
    void has_order_Broadcast(QString DATA);

public slots:
    void updateCount();
    void updateData(qintptr serverSocketID,QString IP,int Port,QByteArray data);
    void judge_order(qintptr serverSocketID,QString IP,int Port,QString order);
    void order_Broadcast(QString DATA);
private slots:
    void on_pushButton_open_clicked();
    void on_pushButton_close_clicked();
    void on_pushButton_clear_clicked();
};

#endif // DIALOG_H

dialog.cpp


#include "dialog.h"
#include "ui_dialog.h"
#include <QHostAddress>
#include <QString>
#include <QNetworkInterface>
#include <qDebug>
int _count;
QByteArray data_all;
//=============构造函数===============================================================
Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    _count=1;
    myserver = new Server(this);
    connect(myserver,SIGNAL(hasConnect(qintptr,QString,int)),this,SLOT(updateCount()));
    connect(myserver,SIGNAL(hasDisConnect(qintptr,QString,int)),this,SLOT(updateCount()));
    connect(myserver,SIGNAL(hasData(qintptr,QString,int,QByteArray)),
            this,SLOT(updateData(qintptr,QString,int,QByteArray)));
    connect(this,SIGNAL(has_order(qintptr,QString,int,QString)),
            this,SLOT(judge_order(qintptr,QString,int,QString)));
    connect(this,SIGNAL(has_order_Broadcast(QString)),
            this,SLOT(order_Broadcast(QString)));

}
//=============虚造函数===============================================================
Dialog::~Dialog()
{
    delete ui;
}
//=============查询本机IP==============================================================
QString Dialog::read_ip_address()
{
    QString ip_address;
    QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
    for (int i = 0; i < ipAddressesList.size(); ++i)
    {
        if (ipAddressesList.at(i) != QHostAddress::LocalHost &&  ipAddressesList.at(i).toIPv4Address())
        {
            ip_address = ipAddressesList.at(i).toString();
        }
    }
    if (ip_address.isEmpty())
        ip_address = QHostAddress(QHostAddress::LocalHost).toString();
    return ip_address;
}
//=============开启服务器===============================================================
void Dialog::on_pushButton_open_clicked()
{
    ui->pushButton_open->setEnabled(false);
    ui->pushButton_close->setEnabled(true);
    int Port = 6666;
    //================================
    ui->label_IP->setText(read_ip_address());
    //================================
    myserver->listen(QHostAddress::Any,Port);//监听客户端连接
    ui->label_Port->setText(QString::number(Port));
    ui->label_status->setText("运行中!");
}
//=============关闭服务器===============================================================
void Dialog::on_pushButton_close_clicked()
{
    myserver->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 Dialog::updateCount()
{
    ui->label_num->setText(QString::number(myserver->serverSocketCount));
    QMap <int,ServerSocket *>::iterator OnLine;

}
//=============接收数据===============================================================
void Dialog::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
    {
        emit has_order(serverSocketID,IP,Port,DATA);
    }
}
//========================================================·====================
void Dialog::judge_order(qintptr serverSocketID,QString IP,int Port,QString order)//judge which order
{
    QByteArray change = order.toUtf8();
    data_all=change;
    QString ORDER=order.mid(1,order.length()-2);
    QStringList List=ORDER.split(";");

    if(List[0]==QString::fromLocal8Bit("data"))
    {
        emit has_order_Broadcast(order);
    }
}
//=====================================================================
void Dialog::order_Broadcast(QString DATA)
{
    QByteArray Broadcast = DATA.toUtf8();
    QMap <int,ServerSocket *>::const_iterator Device;
    for(Device=myserver->idSocketMap.constBegin();Device!=myserver->idSocketMap.constEnd();++Device)
    {
        Device.value()->write(Broadcast);
    }
}
//=====================================================================
void Dialog::on_pushButton_clear_clicked()
{
    ui->plainTextEdit_show->clear();
}

发布了48 篇原创文章 · 获赞 5 · 访问量 2626

猜你喜欢

转载自blog.csdn.net/Mr_robot_strange/article/details/104298997