QT + Tcp客户端,服务器(支持多客户端)

服务器 0

环境

Qt 5.4.2

功能

QT Tcp 服务器,多客户端通信

服务器源码

在这里插入图片描述

  1. TcpServerApp.pro
    QT += network

  2. mainwindow

mainwindow.h

#include "tcpserver.h"class MainWindow : public QMainWindow{    Q_OBJECTpublic:    explicit MainWindow(QWidget *parent = 0);    ~MainWindow();private:    Ui::MainWindow *ui;private:     QTreeWidgetItem *pServerItem;     QTreeWidgetItem *pClientItem;     QStandardItemModel* pClientModel;     TcpServer  tcpServer;private:    void InitTreeView();    void InitServerCfg();    void InitClientCfg();private slots:    void slot_incomingConnect(QString socketID);    void slot_readMessage(QString socketId,QString message);    void slot_disconnected(QString socketId);    void slot_itemDoubleClicked(QTreeWidgetItem *item, int column);    void slot_curStateChanged(QString identify,int state);    void on_pushButton_Start_clicked();    void on_pushButton_Close_clicked();    void on_pushButton_Send_clicked();    void on_pushButton_SendAll_clicked();    void on_pushButton_CloseAll_clicked();};class MyCheckBox : public QCheckBox{    Q_OBJECTpublic:    explicit MyCheckBox(){}    ~MyCheckBox(){}public:    void SetIdentify(QString identify) { sIdentify = identify;     connect(this,SIGNAL(stateChanged(int)),this,SLOT(slot_stateChanged(int)));}signals:    void curStateChanged(QString identify,int state);private slots:    void slot_stateChanged(int state){emit curStateChanged(sIdentify,state);}private:    QString  sIdentify;};#endif // MAINWINDOW_H

mainwindow.cpp

MainWindow::MainWindow(QWidget *parent) :    QMainWindow(parent),    ui(new Ui::MainWindow){    ui->setupUi(this);    InitTreeView();    InitServerCfg();    InitClientCfg();}void MainWindow::InitTreeView(){    ui->treeWidget->setColumnCount(1);    ui->treeWidget->setHeaderLabel(tr("TCP 服务器"));    pServerItem = new QTreeWidgetItem(ui->treeWidget,QStringList(QString("服务器")));// 添加QTreeWidget主节点;    pClientItem = new QTreeWidgetItem(ui->treeWidget,QStringList(QString("客户端")));    QTreeWidgetItem *pServerItem_1 = new QTreeWidgetItem(pServerItem,QStringList(QString("配置管理")));    QTreeWidgetItem *pClientItem_1 = new QTreeWidgetItem(pClientItem,QStringList(QString("配置管理")));    connect(ui->treeWidget,SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),this,SLOT(slot_itemDoubleClicked(QTreeWidgetItem*,int)));    ui->treeWidget->setCurrentItem(pServerItem_1);    ui->treeWidget->expandAll();    ui->stackedWidget->setCurrentIndex(0);}void MainWindow::InitServerCfg(){    connect(&tcpServer,SIGNAL(incomingConnect(QString)),SLOT(slot_incomingConnect(QString)));    connect(&tcpServer,SIGNAL(readMessage(QString,QString)),SLOT(slot_readMessage(QString,QString)));    connect(&tcpServer,SIGNAL(disconnected(QString)),SLOT(slot_disconnected(QString)));    ui->pushButton_Start->setEnabled(true);    ui->pushButton_Close->setEnabled(false);}void MainWindow::InitClientCfg(){    pClientModel = new QStandardItemModel();    ui->tableView_RecvAll->verticalHeader()->setVisible(false);    ui->tableView_RecvAll->horizontalHeader()->setVisible(false);    ui->tableView_RecvAll->setModel(pClientModel);    pClientModel->setColumnCount(2);                                    ui->tableView_RecvAll->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);    ui->tableView_RecvAll->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);    ui->tableView_RecvAll->setColumnWidth(0, 80);    ui->tableView_RecvAll->setEditTriggers(QAbstractItemView::NoEditTriggers);    MyCheckBox *pAllCheck = new MyCheckBox();    pAllCheck->setText("全选");    pAllCheck->SetIdentify("All");    connect(pAllCheck,SIGNAL(curStateChanged(QString,int)),this,SLOT(slot_curStateChanged(QString,int)));    pClientModel->setRowCount(1);    ui->tableView_RecvAll->setRowHeight(0,40);    ui->tableView_RecvAll->setIndexWidget(pClientModel->index(0,0),pAllCheck);    pClientModel->setItem(0, 1, new QStandardItem("客户端" ) );    ui->pushButton_SendAll->setEnabled(false);    ui->pushButton_CloseAll->setEnabled(false);}void MainWindow::slot_incomingConnect(QString socketID){    QTreeWidgetItem *pClientItem_N = new QTreeWidgetItem(pClientItem,QStringList(socketID));    pClientModel->setRowCount(pClientModel->rowCount()+1);    MyCheckBox *pOneCheck = new MyCheckBox();    pOneCheck->SetIdentify(socketID);    connect(pOneCheck,SIGNAL(curStateChanged(QString,int)),this,SLOT(slot_curStateChanged(QString,int)));    ui->tableView_RecvAll->setIndexWidget(pClientModel->index(pClientModel->rowCount()-1,0),pOneCheck);    pClientModel->setItem(pClientModel->rowCount()-1, 1, new QStandardItem(socketID) );    ui->tableView_RecvAll->setRowHeight(pClientModel->rowCount()-1,40);}void MainWindow::slot_readMessage(QString socketId, QString message){    QString sSocketID =  "客户端[" + socketId + "]";    if(ui->label_Info->text() == sSocketID)    {        ui->textEdit_Recv->setText(message);    }}void MainWindow::slot_disconnected(QString socketId){    for(int i=0; i<pClientItem->childCount(); i++)    {        if(pClientItem->child(i)->text(0) == socketId)        {            pClientItem->removeChild(pClientItem->child(i));            break;        }    }        for(int i=1; i<pClientModel->rowCount(); i++)    {        if(socketId == pClientModel->item(i,1)->text())        {            pClientModel->removeRow(i);        }    }    ui->treeWidget->setCurrentItem(pClientItem->child(0));    ui->stackedWidget->setCurrentIndex(1);}void MainWindow::slot_itemDoubleClicked(QTreeWidgetItem *item, int column){    if(NULL == item->parent()) { return; }    if(item->parent() == pServerItem)    {        ui->stackedWidget->setCurrentIndex(0);        return;    }    if("配置管理" == item->text(0))    {       ui->stackedWidget->setCurrentIndex(1);       return;    }    QString sTitleMsg  = "客户端[" + item->text(0) + "]";    ui->label_Info->setText(sTitleMsg);    ui->stackedWidget->setCurrentIndex(2);    ui->textEdit_Send->clear();    ui->textEdit_Recv->setText(tcpServer.GetRecvMesg(item->text(0)));}void MainWindow::slot_curStateChanged(QString identify, int state){   if("All" != identify) { return; }   MyCheckBox *pCheckBox;      for(int i=1; i<pClientModel->rowCount(); i++)   {       pCheckBox = (MyCheckBox*)ui->tableView_RecvAll->indexWidget(pClientModel->index(i,0));       switch(state)       {        case 0: pCheckBox->setChecked(false); break;        case 2: pCheckBox->setChecked(true);  break;        default:break;       }   }}void MainWindow::on_pushButton_Start_clicked(){    ui->label_ServerSts->setText("");    if(!tcpServer.listen(QHostAddress::Any,ui->spinBox_Port->value()))    {        ui->label_ServerSts->setText("Failed to bind port !");        return;    }    ui->pushButton_Start->setEnabled(false);    ui->pushButton_Close->setEnabled(true);    ui->pushButton_SendAll->setEnabled(true);    ui->pushButton_CloseAll->setEnabled(true);}void MainWindow::on_pushButton_Close_clicked(){    tcpServer.close();    tcpServer.ClearClientAll();    ui->pushButton_Start->setEnabled(true);    ui->pushButton_Close->setEnabled(false);    ui->pushButton_SendAll->setEnabled(false);    ui->pushButton_CloseAll->setEnabled(false);}void MainWindow::on_pushButton_Send_clicked(){    QString sSocketID =  ui->label_Info->text();    sSocketID = sSocketID.mid(sSocketID.indexOf("[")+1,sSocketID.lastIndexOf("]") - sSocketID.indexOf("[")-1);    tcpServer.SendMessage(sSocketID,ui->textEdit_Send->toPlainText());    ui->textEdit_Send->clear();    ui->textEdit_Recv->setText(tcpServer.GetRecvMesg(sSocketID));}void MainWindow::on_pushButton_SendAll_clicked(){    if("" == ui->textEdit_RecvAll->toPlainText()) { return; }    MyCheckBox *pCheckBox;    for(int i=1; i<pClientModel->rowCount(); i++)    {        pCheckBox = (MyCheckBox*)ui->tableView_RecvAll->indexWidget(pClientModel->index(i,0));        switch(pCheckBox->checkState())        {          case Qt::Checked :          {            tcpServer.SendMessage(pClientModel->item(i,1)->text(),ui->textEdit_RecvAll->toPlainText());          }break;          default:break;        }    }}void MainWindow::on_pushButton_CloseAll_clicked(){    MyCheckBox *pCheckBox;    for(int i=1; i<pClientModel->rowCount(); i++)    {        pCheckBox = (MyCheckBox*)ui->tableView_RecvAll->indexWidget(pClientModel->index(i,0));        switch(pCheckBox->checkState())        {          case Qt::Checked :          {            tcpServer.CloseSocket(pClientModel->item(i,1)->text());          }break;          default:break;        }    }}
  1. tcpserver
    tcpserver.h
#include "tcpsocket.h"class TcpServer : public QTcpServer{    Q_OBJECTpublic:    TcpServer();    ~TcpServer();    void ClearClientAll();    void SendMessage(QString socketId,QString message);    void CloseSocket(QString socketId);    QString GetRecvMesg(QString socketId);protected:    void incomingConnection(int socketId);private:    QMap<QString,TcpSocket *> clientArray;private slots:    void slot_readMsg(QString socketId,QString message);    void slot_disconnect(QString socketId);signals:    void incomingConnect(QString socketId);    void readMessage(QString socketId,QString message);    void disconnected(QString socketId);};#endif // TCPSERVER_H

tcpserver.cpp

#include "tcpserver.h"void TcpServer::ClearClientAll(){    for (QString key : clientArray.keys())    {        clientArray[key]->close();    }    clientArray.clear();}void TcpServer::SendMessage(QString socketId, QString message){    if(clientArray.contains(socketId))    {        clientArray[socketId]->SendMessage(message);    }}void TcpServer::CloseSocket(QString socketId){    if(clientArray.contains(socketId))    {        clientArray[socketId]->close();    }}QString TcpServer::GetRecvMesg(QString socketId){    if(clientArray.contains(socketId))    {        return clientArray[socketId]->GetRecvMesg();    }}void TcpServer::incomingConnection(int socketId){   TcpSocket *pTcpSocket = new TcpSocket();   pTcpSocket->setSocketDescriptor(socketId);   QString sClientInfo =  "ID:"+QString::number(socketId) + ",IP:" + pTcpSocket->peerAddress().toString() + ":"+ QString::number(pTcpSocket->peerPort());   pTcpSocket->SetSocketID(sClientInfo);   clientArray.insert(sClientInfo,pTcpSocket);   connect(pTcpSocket,SIGNAL(readMsg(QString,QString)),SLOT(slot_readMsg(QString,QString)));   connect(pTcpSocket,SIGNAL(disconnect(QString)),SLOT(slot_disconnect(QString)));   emit incomingConnect(sClientInfo);}void TcpServer::slot_readMsg(QString socketId, QString message){    emit readMessage(socketId,message);}void TcpServer::slot_disconnect(QString socketId){   clientArray[socketId]->close();   clientArray.remove(socketId);   emit disconnected(socketId);}
  1. tcpsocket
    tcpsocket.h
class TcpSocket : public QTcpSocket{    Q_OBJECTpublic:    TcpSocket();    ~TcpSocket();    void SetSocketID(QString socketID);    void SendMessage(QString message);    QString GetRecvMesg();private:    QString sSocketID;    QStringList sRecvMesg;private slots:    void slot_readyRead();    void slot_disconnected();signals:    void readMsg(QString socketId,QString message);    void disconnect(QString socketId);};#endif // TCPSOCKET_H

tcpsocket.cpp

TcpSocket::TcpSocket(){    sSocketID = "";    sRecvMesg.clear();    connect(this,SIGNAL(readyRead()),this,SLOT(slot_readyRead()));    connect(this,SIGNAL(disconnected()),this,SLOT(slot_disconnected()));}void TcpSocket::SetSocketID(QString socketID){    sSocketID = socketID;}void TcpSocket::SendMessage(QString message){    this->write(message.toLatin1());    if(sRecvMesg.count() > 1024) { sRecvMesg.removeAt(0);}    QString sReadMsg = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + ": S -> " + message;    sRecvMesg.append(sReadMsg);}QString TcpSocket::GetRecvMesg(){    return sRecvMesg.join("/n");}void TcpSocket::slot_readyRead(){    if(sRecvMesg.count() > 1024) { sRecvMesg.removeAt(0);}    QString sReadMsg = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + ": R -> " + QString(this->readAll());    sRecvMesg.append(sReadMsg);    emit readMsg(sSocketID,sRecvMesg.join("/n"));}void TcpSocket::slot_disconnected(){    emit disconnect(sSocketID);}

客户端源码

在这里插入图片描述

  1. TcpClientApp.pro
    QT += network

  2. mainwindow
    mainwindow.h

class MainWindow : public QMainWindow{    Q_OBJECTpublic:    explicit MainWindow(QWidget *parent = 0);    ~MainWindow();private:    Ui::MainWindow *ui;private slots:    void slot_connected();    void slot_readyRead();    void slot_disconnected();    void on_pushButton_Connect_clicked();    void on_pushButton_Send_clicked();    void on_pushButton_Close_clicked();private:    QTcpSocket tcpSocket;};#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :    QMainWindow(parent),    ui(new Ui::MainWindow){    ui->setupUi(this);    connect(&tcpSocket,SIGNAL(connected()),this,SLOT(slot_connected()));    connect(&tcpSocket,SIGNAL(readyRead()),this,SLOT(slot_readyRead()));    connect(&tcpSocket,SIGNAL(disconnected()),this,SLOT(slot_disconnected()));    ui->label_sts->setText("disconnected");    ui->pushButton_Connect->setEnabled(true);    ui->pushButton_Send->setEnabled(false);    ui->pushButton_Close->setEnabled(false);}void MainWindow::slot_connected(){    ui->label_sts->setText("connected");    ui->pushButton_Connect->setEnabled(false);    ui->pushButton_Send->setEnabled(true);    ui->pushButton_Close->setEnabled(true);}void MainWindow::slot_readyRead(){    QString sMessage = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + ": R -> " + QString(tcpSocket.readAll());    if(ui->textEdit_Recv->document()->lineCount() > 1024)    {        ui->textEdit_Recv->clear();    }    ui->textEdit_Recv->append(sMessage);}void MainWindow::slot_disconnected(){    ui->label_sts->setText("disconnected");    ui->pushButton_Connect->setEnabled(true);    ui->pushButton_Send->setEnabled(false);    ui->pushButton_Close->setEnabled(false);}void MainWindow::on_pushButton_Connect_clicked(){    tcpSocket.connectToHost(QHostAddress(ui->lineEdit_IP->text()),ui->spinBox_Port->value());}void MainWindow::on_pushButton_Send_clicked(){    tcpSocket.write(ui->textEdit_Send->toPlainText().toLatin1());    if(ui->textEdit_Recv->document()->lineCount() > 1024)    {        ui->textEdit_Recv->clear();    }    QString sMessage = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + ": S -> " + ui->textEdit_Send->toPlainText();    ui->textEdit_Recv->append(sMessage);    ui->textEdit_Send->clear();}void MainWindow::on_pushButton_Close_clicked(){    tcpSocket.close();}

运行结果

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

也许您对下面的内容还感兴趣: