QtTCP通信过程
在 Qt 中实现 TCP/IP 服务器端通信的流程:
-
创建套接字
-
将套接字设置为监听模式
-
等待并接受客户端请求
可以通过 QTcpServer
提供的 void newConnection()信号来检测是否有连
接请求,如果有可以在对应的槽函数中调用 nextPendingConnection
函数获
取到客户端的 Socket
信息(返回值为 QTcpSocket*类型指针),通过此套接
字与客户端之间进行通信。
-
接收或者向客户端发送数据
-
接收数据:使用
read()
或者readAll()
函数 -
发送数据:使用
write()
函数
-
客户端通信流程:
-
创建套接字
-
连接服务器
可以使用 QTcpSocket
类的 **connectToHost()**函数来连接服务器。
- 向服务器发送或者接受数据
下面例子为简单的 TCP/IP 通信的实现:
服务器端
Widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTcpServer> //监听套接字
#include <QTcpSocket> //通信套接字
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_pushButtonSent_clicked();
void on_pushButtonClose_clicked();
private:
Ui::Widget *ui;
QTcpServer *tcpServer; //监听套接字
QTcpSocket *tcpSocket; //通信套接字
};
#endif // WIDGET_H
Widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
tcpServer = NULL;
tcpSocket = NULL;
//监听套接字
tcpServer = new QTcpServer(this); //this:指定父对象让其自动回收空间
tcpServer->listen(QHostAddress::Any, 8888);
setWindowTitle("服务器;端口:8888");
connect(tcpServer, &QTcpServer::newConnection,
[=]()
{
//取出建立好链接的套接字
tcpSocket = tcpServer->nextPendingConnection(); //取当前最新的那个套接字
//获取对方的IP和端口
QString ip = tcpSocket->peerAddress().toString();
qint16 port = tcpSocket->peerPort();
QString temp = QString("[%1:%2]:成功连接").arg(ip).arg(port);
ui->textEditRead->setText(temp);
connect(tcpSocket, &QTcpSocket::readyRead,
[=]()
{
QByteArray array = tcpSocket->readAll();
ui->textEditRead->append(array);
}
);
}
);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButtonSent_clicked()
{
if(tcpSocket == NULL) return;
//获取编辑区内容
QString str = ui->textEditWrite->toPlainText();
//对方发送数据,使用套接字是tcpSocket
tcpSocket->write( str.toUtf8().data() );
ui->textEditWrite->clear(); //清空编辑区
}
void Widget::on_pushButtonClose_clicked()
{
if(tcpSocket == NULL) return;
//主动和客户端断开连接
tcpSocket->disconnectFromHost();
tcpSocket->close();
tcpSocket = NULL;
}
客户端
ClentWidget.h
#ifndef CLENTWIDGET_H
#define CLENTWIDGET_H
#include <QWidget>
#include <QTcpSocket> //通信套接字
#include <QString>
namespace Ui {
class ClentWidget;
}
class ClentWidget : public QWidget
{
Q_OBJECT
public:
explicit ClentWidget(QWidget *parent = nullptr);
~ClentWidget();
private slots:
void on_pushButtonSent_clicked();
void on_pushButtonConnect_clicked();
void on_pushButtonClose_clicked();
private:
Ui::ClentWidget *ui;
QTcpSocket *m_client;
};
#endif // CLENTWIDGET_H
ClentWidget.cpp
#include "clentwidget.h"
#include "ui_clentwidget.h"
#include <QHostAddress>
ClentWidget::ClentWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::ClentWidget)
{
ui->setupUi(this);
setWindowTitle("客户端");
m_client = new QTcpSocket(this); //创建套接字
connect(m_client, &QTcpSocket::connected,
[=]()
{
ui->textEditRead->setText("与服务器:连接成功");
}
);
//通过信号接受服务器数据
connect(m_client, &QTcpSocket::readyRead,
[=]()
{
QByteArray array = m_client->readAll();
ui->textEditRead->append( array );
}
);
}
ClentWidget::~ClentWidget()
{
delete ui;
}
void ClentWidget::on_pushButtonSent_clicked()
{
QString strText = ui->textEditWrite->toPlainText();
//发送数据
m_client->write( strText.toUtf8().data() );
ui->textEditWrite->clear();
}
void ClentWidget::on_pushButtonConnect_clicked()
{
//获取服务器IP和端口
QString strIp = ui->lineEditServerIP->text();
qint16 port = ui->lineEditServerPort->text().toInt();
//连接服务器
m_client->connectToHost(QHostAddress(strIp), port);
}
void ClentWidget::on_pushButtonClose_clicked()
{
//与服务器断开连接
m_client->disconnectFromHost();
m_client->close();
ui->textEditRead->setText("与服务器:断开连接" );
}