一、项目概述
1.功能介绍
•支持开启服务端监听,客户端连接
•支持客户端、服务端收发消息
•支持多客户端连接服务端
2.界面预览
二、常用类
在此主要罗列一些主要使用的类,具体请查阅QT帮助手册
•QTcpServer
•QTcpSocket
•QNetworkInterface
•QHostAddress
•QMouseEvent
•QTextCharFormat
三、项目源码
https://github.com/GeekerGao/TCP-Client-Server
若Github登陆不上,可私信要网盘链接!
部分代码
server
#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>
#include <QNetworkInterface>
#include <QTcpSocket>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->setLayout(ui->verticalLayout);
server = new QTcpServer(this);
connect(ui->comboBoxChildren,&MyComboBox::on_ComboBox_clicked,this,&Widget::mComboBox_refresh);
connect(server,SIGNAL(newConnection()),this,SLOT(on_newClient_connect()));
ui->btnApart->setEnabled(false);
ui->btnStopListen->setEnabled(false);
ui->btnSend->setEnabled(false);
QList<QHostAddress> address = QNetworkInterface::allAddresses();
for(QHostAddress tmp : address){
if(tmp.protocol() == QAbstractSocket::IPv4Protocol){
ui->comboBoxAddr->addItem(tmp.toString());
}
}
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_newClient_connect()
{
if(server->hasPendingConnections()){
QTcpSocket* connection = server->nextPendingConnection();
ui->textEditRev->insertPlainText("客户端地址:"+connection->peerAddress().toString()
+"\n客户端端口号:"+QString::number(connection->peerPort())+"\n");
connect(connection,SIGNAL(readyRead()),this,SLOT(on_readyRead_handler()));
connect(connection,SIGNAL(stateChanged(QAbstractSocket::SocketState)),
this,SLOT(mstateChanged(QAbstractSocket::SocketState)));
ui->comboBoxChildren->addItem(QString::number(connection->peerPort()));
ui->comboBoxChildren->setCurrentText(QString::number(connection->peerPort()));
if(!ui->btnSend->isEnabled()){
ui->btnSend->setEnabled(true);
}
}
}
void Widget::on_btnListen_clicked()
{
int port = ui->lineEditPort->text().toInt();
if(!server->listen(QHostAddress(ui->comboBoxAddr->currentText()),port)){
QMessageBox msgBox;
msgBox.setWindowTitle("监听失败");
msgBox.setText("端口号被占用");
msgBox.exec();
return;
}
ui->btnListen->setEnabled(false);
ui->btnApart->setEnabled(true);
ui->btnStopListen->setEnabled(true);
}
void Widget::on_readyRead_handler()
{
QTcpSocket *tmpSock = qobject_cast<QTcpSocket *>(sender());
QByteArray revData = tmpSock->readAll();
ui->textEditRev->moveCursor(QTextCursor::End);
ui->textEditRev->ensureCursorVisible();
ui->textEditRev->insertPlainText("客户端:"+revData+"\n");
}
void Widget::mdisconnected()
{
QTcpSocket *tmpSock = qobject_cast<QTcpSocket *>(sender());
ui->textEditRev->insertPlainText("客户端断开!\n");
tmpSock->deleteLater();
}
void Widget::mstateChanged(QAbstractSocket::SocketState socketState)
{
int tmpIndex;
QTcpSocket *tmpSock = qobject_cast<QTcpSocket *>(sender());
switch(socketState){
case QAbstractSocket::UnconnectedState:
ui->textEditRev->insertPlainText("客户端断开!\n");
tmpIndex = ui->comboBoxChildren->findText(QString::number(tmpSock->peerPort()));
ui->comboBoxChildren->removeItem(tmpIndex);
tmpSock->deleteLater();
if(ui->comboBoxChildren->count() == 0)
ui->btnSend->setEnabled(false);
break;
case QAbstractSocket::ConnectedState:
case QAbstractSocket::ConnectingState:
ui->textEditRev->insertPlainText("客户端接入!");
break;
}
}
void Widget::mComboBox_refresh()
{
ui->comboBoxChildren->clear();
QList<QTcpSocket*> tcpSocketClients = server->findChildren<QTcpSocket*>();
for(QTcpSocket* tmp : tcpSocketClients){
if(tmp != nullptr)
ui->comboBoxChildren->addItem(QString::number(tmp->peerPort()));
}
ui->comboBoxChildren->addItem("All");
}
void Widget::on_btnSend_clicked()
{
QList<QTcpSocket*> tcpSocketClients = server->findChildren<QTcpSocket*>();
//当用户不选择向所有客户端进行发送时候
if(tcpSocketClients.isEmpty()){
QMessageBox msgBox;
msgBox.setWindowTitle("发送错误!");
msgBox.setText("当前无连接!");
msgBox.exec();
ui->btnSend->setEnabled(false);
return;
}
if(ui->comboBoxChildren->currentText() != "All"){
QString currentName = ui->comboBoxChildren->currentText();
for(QTcpSocket* tmp : tcpSocketClients){
if(QString::number(tmp->peerPort()) == currentName){
tmp->write(ui->textEditSend->toPlainText().toStdString().c_str());
}
}
}else{
//遍历所有子客户端,并一一调用write函数,向所有客户端发送消息
for(QTcpSocket* tmp : tcpSocketClients){
QByteArray sendData = ui->textEditSend->toPlainText().toUtf8();
tmp->write(sendData);
}
}
}
void Widget::on_btnStopListen_clicked()
{
QList<QTcpSocket*> tcpSocketClients = server->findChildren<QTcpSocket*>();
for(QTcpSocket* tmp : tcpSocketClients){
tmp->close();
}
server->close();
ui->btnListen->setEnabled(true);
ui->btnApart->setEnabled(false);
ui->btnStopListen->setEnabled(false);
}
void Widget::on_btnApart_clicked()
{
on_btnStopListen_clicked();
delete server;
this->close();
}
client
#include "widget.h"
#include "ui_widget.h"
#include <QTimer>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->setLayout(ui->verticalLayout);
ui->btnDisconnected->setEnabled(false);
ui->btnSend->setEnabled(false);
client = new QTcpSocket(this);
connect(client,SIGNAL(readyRead()),this,SLOT(mRead_data_From_Server()));
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_btnConnected_clicked()
{
client->connectToHost(ui->lineEditIPAddr->text(),ui->lineEditPort->text().toInt());
timer = new QTimer(this);
timer->setSingleShot(true);
timer->setInterval(5000);
connect(timer,SIGNAL(timeout()),this,SLOT(onTimeout()));
connect(client,SIGNAL(connected()),this,SLOT(onConnected()));
connect(client,SIGNAL(error(QAbstractSocket::SocketError)),
this,SLOT(onError(QAbstractSocket::SocketError)));
this->setEnabled(false);
timer->start();
}
void Widget::mRead_data_From_Server()
{
ui->textEditRev->moveCursor(QTextCursor::End);
ui->textEditRev->ensureCursorVisible();
mInsertTextByColor(Qt::black,client->readAll());
}
void Widget::on_btnSend_clicked()
{
QByteArray sendData = ui->textEditSend->toPlainText().toUtf8();
client->write(sendData);
mInsertTextByColor(Qt::red,sendData);
}
void Widget::on_btnDisconnected_clicked()
{
client->disconnectFromHost();
client->close();
ui->textEditRev->append("中止连接!");
ui->btnConnected->setEnabled(true);
ui->lineEditPort->setEnabled(true);
ui->lineEditIPAddr->setEnabled(true);
ui->btnDisconnected->setEnabled(false);
ui->btnSend->setEnabled(false);
}
void Widget::onConnected()
{
timer->stop();
this->setEnabled(true);
ui->textEditRev->append("连接成功!");
ui->btnConnected->setEnabled(false);
ui->lineEditPort->setEnabled(false);
ui->lineEditIPAddr->setEnabled(false);
ui->btnDisconnected->setEnabled(true);
ui->btnSend->setEnabled(true);
}
void Widget::onError(QAbstractSocket::SocketError error)
{
ui->textEditRev->insertPlainText("连接出问题:"+client->errorString());
this->setEnabled(true);
on_btnDisconnected_clicked();
}
void Widget::onTimeout()
{
ui->textEditRev->insertPlainText("连接超时!");
client->abort();
this->setEnabled(true);
}
void Widget::mInsertTextByColor(Qt::GlobalColor color,QString str)
{
QTextCursor cursor = ui->textEditRev->textCursor();
QTextCharFormat format;
format.setForeground(QBrush(QColor(color)));
cursor.setCharFormat(format);
cursor.insertText(str);
}