环境
Qt 5.4.2
功能
QT Tcp 服务器,多客户端通信
服务器源码
-
TcpServerApp.pro
QT += network -
mainwindow
mainwindow.h
#include "tcpserver.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
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_OBJECT
public:
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;
}
}
}
- tcpserver
tcpserver.h
#include "tcpsocket.h"
class TcpServer : public QTcpServer
{
Q_OBJECT
public:
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);
}
- tcpsocket
tcpsocket.h
class TcpSocket : public QTcpSocket
{
Q_OBJECT
public:
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);
}
客户端源码
-
TcpClientApp.pro
QT += network -
mainwindow
mainwindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
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();
}
运行结果