最近学习了QT的TCP通信,与大家分享下刚开始写TCP通信的一些经验。下面简单写了个TCP服务端的小例程。
基本步骤
- 新建一个工程,在.pro文件中添加
QT += network
- 在.h文件中添加头文件
#include <QTcpServer>
#include <QTcpSocket>
- 在.h添加私有成员对象
QTcpServer *tcpServer;
QTcpSocket *tcpServerForclient;
QList<QTcpSocket*> tcpServerForclientList;
- cpp文件中实例化对象
tcpServer = new QTcpServer(this);
- tcpServer有新的客户端连接会触发newConnection信号,绑定信号对应的槽函数
connect(tcpServer, &QTcpServer::newConnection, this, &MainWindow::newConnectionslot);
-
编辑ui界面
-
新的连接槽函数
void MainWindow::newConnectionslot()
{
QList<QTcpSocket*> tcpServerForclientList;
tcpServerForclient = tcpServer->nextPendingConnection();
tcpServerForclientList.append(tcpServerForclient);
ui->cmBx_client->addItem(tr("%1:%2").arg(tcpServerForclient->peerAddress().toString().split("::ffff:")[1])\
.arg(tcpServerForclient->peerPort()));
qDebug()<<tcpServerForclient->peerAddress().toString();
qDebug()<<tcpServerForclient->peerPort();
connect(tcpServerForclient, &QTcpSocket::readyRead, this, &MainWindow::tcpserverreaddata);
connect(tcpServerForclient, &QTcpSocket::disconnected, this, &MainWindow::disconnectedslot);
}
- 收到客户端发来数据会触发readyRead信号,绑定对应槽函数
void MainWindow::tcpserverreaddata()
{
for (int i=0;i<tcpServerForclientList.length();i++) {
QByteArray buffer = tcpServerForclientList.at(i)->readAll();
if(!buffer.isEmpty())
{
QString recstr = QString::fromLocal8Bit(buffer);
ui->txEt_data->append("收到"+tcpServerForclientList.at(i)->peerAddress().toString().split("::ffff:")[1]
+":"+QString::number(tcpServerForclientList.at(i)->peerPort())
+"的数据:"+recstr);
}
}
}
- 收到客户端断开连接会触发disconnected信号,绑定对应槽函数
void MainWindow::disconnectedslot()
{
for(int i=0; i<tcpServerForclientList.length(); i++)
{
if(tcpServerForclientList.at(i)->state() == QAbstractSocket::UnconnectedState)
{
// 删除存储在combox中的客户端信息
ui->cmBx_client->removeItem(ui->cmBx_client->findText(tr("%1:%2")\
.arg(tcpServerForclientList.at(i)->peerAddress().toString().split("::ffff:")[1])\
.arg(tcpServerForclientList.at(i)->peerPort())));
// 删除存储在tcpClient列表中的客户端信息
tcpServerForclientList.at(i)->destroyed();
tcpServerForclientList.removeAt(i);
}
}
}
- 监听按钮槽函数
void MainWindow::on_psBt_listen_clicked()
{
if(ui->psBt_listen->text() == "监听") {
if(tcpServer->listen(QHostAddress::Any, ui->lnEt_port->text().toUShort())) {
qDebug()<<"listen ok";
ui->psBt_listen->setText("已监听");
}
}
else {
foreach (QTcpSocket *client, tcpServerForclientList) {
client->disconnectFromHost();
}
tcpServer->close(); //不再监听端口
ui->psBt_listen->setText("监听");
}
}
- 发送数据槽函数
void MainWindow::on_psBt_send_clicked()
{
for(int i=0;i<tcpServerForclientList.length();i++) {
if((tcpServerForclientList.at(i)->peerAddress().toString().split("::ffff:")[1]
+":"+QString::number(tcpServerForclientList.at(i)->peerPort())) == ui->cmBx_client->currentText()) {
QString sendstr = ui->txEt_senddata->toPlainText();
tcpServerForclientList.at(i)->write(sendstr.toLocal8Bit());
ui->txEt_data->append("发给"+ui->cmBx_client->currentText()+"的数据:"+sendstr);
}
}
}
完整代码
- mainwindow.h文件:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
public slots:
void newConnectionslot(void);
void tcpserverreaddata(void);
void disconnectedslot(void);
private slots:
void on_psBt_listen_clicked();
void on_psBt_send_clicked();
private:
Ui::MainWindow *ui;
QTcpServer *tcpServer;
QTcpSocket *tcpServerForclient;
QList<QTcpSocket*> tcpServerForclientList;
};
#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);
tcpServer = new QTcpServer(this);
connect(tcpServer, &QTcpServer::newConnection, this, &MainWindow::newConnectionslot);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::newConnectionslot()
{
tcpServerForclient = tcpServer->nextPendingConnection();
tcpServerForclientList.append(tcpServerForclient);
ui->cmBx_client->addItem(tr("%1:%2").arg(tcpServerForclient->peerAddress().toString().split("::ffff:")[1])\
.arg(tcpServerForclient->peerPort()));
qDebug()<<tcpServerForclient->peerAddress().toString();
qDebug()<<tcpServerForclient->peerPort();
connect(tcpServerForclient, &QTcpSocket::readyRead, this, &MainWindow::tcpserverreaddata);
connect(tcpServerForclient, &QTcpSocket::disconnected, this, &MainWindow::disconnectedslot);
}
void MainWindow::on_psBt_listen_clicked()
{
if(ui->psBt_listen->text() == "监听") {
if(tcpServer->listen(QHostAddress::Any, ui->lnEt_port->text().toUShort())) {
qDebug()<<"listen ok";
ui->psBt_listen->setText("已监听");
}
}
else {
foreach (QTcpSocket *client, tcpServerForclientList) {
client->disconnectFromHost();
}
tcpServer->close(); //不再监听端口
ui->psBt_listen->setText("监听");
}
}
void MainWindow::tcpserverreaddata()
{
for (int i=0;i<tcpServerForclientList.length();i++) {
QByteArray buffer = tcpServerForclientList.at(i)->readAll();
if(!buffer.isEmpty())
{
QString recstr = QString::fromLocal8Bit(buffer);
ui->txEt_data->append("收到"+tcpServerForclientList.at(i)->peerAddress().toString().split("::ffff:")[1]
+":"+QString::number(tcpServerForclientList.at(i)->peerPort())
+"的数据:"+recstr);
}
}
}
void MainWindow::disconnectedslot()
{
for(int i=0; i<tcpServerForclientList.length(); i++)
{
if(tcpServerForclientList.at(i)->state() == QAbstractSocket::UnconnectedState)
{
// 删除存储在combox中的客户端信息
ui->cmBx_client->removeItem(ui->cmBx_client->findText(tr("%1:%2")\
.arg(tcpServerForclientList.at(i)->peerAddress().toString().split("::ffff:")[1])\
.arg(tcpServerForclientList.at(i)->peerPort())));
// 删除存储在tcpClient列表中的客户端信息
tcpServerForclientList.at(i)->destroyed();
tcpServerForclientList.removeAt(i);
}
}
}
void MainWindow::on_psBt_send_clicked()
{
for(int i=0;i<tcpServerForclientList.length();i++) {
if((tcpServerForclientList.at(i)->peerAddress().toString().split("::ffff:")[1]
+":"+QString::number(tcpServerForclientList.at(i)->peerPort())) == ui->cmBx_client->currentText()) {
QString sendstr = ui->txEt_senddata->toPlainText();
tcpServerForclientList.at(i)->write(sendstr.toLocal8Bit());
ui->txEt_data->append("发给"+ui->cmBx_client->currentText()+"的数据:"+sendstr);
}
}
}
运行结果
代码下载地址工程文件