QT TCP通信保证Client自动连接Server

问题

对TCP有了解的小伙伴知道,Server开启端口后一直处于监听状态,Client需要主动去连接到该端口,也就是需要保证Server先开启,然后Client再连接到该Server。现在有一个项目,同一台电脑内的两个进程ProcessA、ProcessB分别作为Server、Client进行通信,通常做法是用户需要先保证ProcessA(Server)先运行,然后开启ProcessB并手动连接。现在想要设计一种通信机制,避免用户手动建立Server和Client之间的通信,能够做到通信自动化。

通信设计

建立一个新的Client,其作用就是以一定周期不断尝试与Server建立,如果连接上Server就发出相应的连接成功信号,外部代码可以写代码绑定该信号,以便在检测到Server开启后业务Client也能迅速连上。

  1. 新Client以一定timeout尝试连接到Server,连接不上的情况就使用定时器Timer触发重新连接槽函数重新连接Server;
  2. 连接上Server后发出连接成功信号——signal_connected,并中断Timer,以避免无所谓的重新连接;
  3. 为新Client断开连接绑定重新连接的槽函数,重新回到步骤1重连。

代码

就只有一个包含函数定义的头文件——TcpClient.h。

#pragma once
#include <QObject>
#include <QTcpSocket>
#include <QTimer>

//该客户端为死缠烂打式client,一旦为其分配连接的server,将会一直寻求连接,
//直到连接上,即使断开也会再次不断尝试连接,直到连接或退出
class TcpClient : public QObject
{
	Q_OBJECT
private:
	QTcpSocket* tcpSocket = nullptr;
	QString host = "";
	quint16 port = 8080;
	QTimer reconnectTimer;
	int m_reconnectTime = 500;//单位为毫秒

public:
	explicit TcpClient(QObject* parent = nullptr) : QObject(parent)
	{
		// 创建 TCP socket
		tcpSocket = new QTcpSocket(this);

		QObject::connect(&reconnectTimer, &QTimer::timeout, [&]() {
			Connect();
			});

		// 连接信号槽
		QObject::connect(tcpSocket, &QTcpSocket::connected, [&]() {
			reconnectTimer.stop();
			signal_connected();
			});
		QObject::connect(tcpSocket, &QTcpSocket::disconnected, [&]() {
			Connect();
			emit disconnected();
			});
		QObject::connect(tcpSocket, &QTcpSocket::readyRead, [&]() {
			QByteArray data = tcpSocket->readAll();
			emit signal_messageReceived(QString::fromLocal8Bit(data.data()));
			});

		
	}

	~TcpClient()
	{
		if (tcpSocket != nullptr)
		{
			tcpSocket->disconnectFromHost();
			delete tcpSocket;
			tcpSocket = nullptr;
		}
	}

	//void Connect(QString ipAddr,int port)
	//{
	//	this->host = ipAddr;
	//	this->port = port;
	//	tcpSocket->connectToHost(this->host, port);
	//}
	// 连接服务器
	void connectToServer(QString hostAddress, int port)
	{
		this->host = hostAddress;
		this->port = port;
		Connect();		
	}

	void connectToServerOfWait(const QString& hostAddress, quint16 port,int msecs =3000)
	{
		tcpSocket->waitForConnected(msecs);
	}

	// 断开连接
	void disconnectFromServer()
	{
		tcpSocket->disconnectFromHost();
	}

	// 发送消息(QString)
	void sendMessage(const QString& message)
	{
		if (!isConnected()) return;
		tcpSocket->write(message.toUtf8());
	}

	// 检查是否连接
	bool isConnected() const
	{
		return tcpSocket->state() == QAbstractSocket::ConnectedState;
	}

signals:
	// 连接成功信号
	void signal_connected();

	// 连接断开信号
	void disconnected();

	// 接收到消息信号
	void signal_messageReceived(const QString& message);

public:
	// 发送消息
	void sendMessage(const QByteArray& message)
	{
		tcpSocket->write(message);
	}

	void Connect() {
		qDebug() << "Connect()+1 with " << QString("(%1, %2)").arg(host).arg(port);
		tcpSocket->connectToHost(host, port);
		if (!tcpSocket->waitForConnected(m_reconnectTime)) {
			reconnectTimer.start(m_reconnectTime); // m_reconnectTime毫秒后重连
		}
	}
};

类使用
只需为信号signal_connected绑定槽函数,该槽函数里包含业务Client连接到Server的代码。

		TcpClient* m_reconnnectTcpClient = new TcpClient(this);
		QObject::connect(m_reconnnectTcpClient, &TcpClient::signal_connected, [&] {on_tcpConnnected();});

		m_reconnnectTcpClient->connectToServer(fromStdString(m_rpcIP), m_rpcPort);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值