环境
Qt 5.4.2
功能
QT Tcp 服务器,多客户端通信
服务器源码
-
TcpServerApp.pro
QT += network -
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; } }}
- 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);}
- 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);}
客户端源码
-
TcpClientApp.pro
QT += network -
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();}
运行结果