QT TCP功能实现类
QT封装了QTcpSocket 类和QTcpServer类用于实现TCP通信功能可点击QTcpSocket官方说明以及QTcpServer官方说明查看。
二次封装说明
服务器类以及客户端类都封装了sendMsg槽函数用于发送数据以及slotDataRecived槽函数用于接收数据。可根据实际需要对这两个函数进行再次封装。
功能代码
tcpService.h
#pragma once
#include <QObject>
#include <QTcpSocket>
#include <QTcpServer>
#include <unordered_map>
#include <mutex>
class TcpSocket : public QTcpSocket
{
Q_OBJECT //添加宏以实现信号槽通信机制
public:
TcpSocket(void);
~TcpSocket(void) {};
signals:
/*
@brife 套接字断开连接信号
@param descriptor 套接字文件描述符
*/
void socketDisconnected(const qintptr& descriptor);
/*
@brife 数据接收信号
@param msg 数据
*/
void socketRecived(const QByteArray& msg);
protected slots:
/*
@brife 套接字断开连接槽函数
*/
void slotSocketDisconnected(void);
/*
@brife 数据接收槽函数
*/
void slotSocketRecived(void);
};
class TcpService : public QTcpServer
{
Q_OBJECT //添加宏以实现信号槽通信机制
private:
//连接的套接字
std::unordered_map<qintptr, TcpSocket*> mConnectSocket;
std::mutex mConnectSocketMutex;
public:
TcpService(const QHostAddress& addr, const int& port);
~TcpService();
protected slots:
/*
@brife 套接字断开连接槽函数
@param descriptor 套接字文件描述符
*/
virtual void slotSocketDisconnected(const qintptr& descriptor);
/*
@brife 接收数据槽函数
*/
virtual void slotDataRecived(const QByteArray& msg);
protected:
/*
@brife 套接字连接回调
@param socketDescriptor 套接字描述符
*/
virtual void incomingConnection(qintptr socketDescriptor) override;
public:
/*
@brife 发送数据
@param msg 数据信息
@param len 数长度
*/
void sendMsg(const char* msg, const qint64& len);
};
tcpService.cpp
#include "tcpService.h"
#include <QDebug>
TcpSocket::TcpSocket(void)
{
connect(this, &QTcpSocket::disconnected, this, &TcpSocket::slotSocketDisconnected);
connect(this, &QTcpSocket::readyRead, this, &TcpSocket::slotSocketRecived);
}
void TcpSocket::slotSocketDisconnected(void)
{
emit socketDisconnected(this->socketDescriptor());
}
void TcpSocket::slotSocketRecived(void)
{
while (0 < this->bytesAvailable())
{
QByteArray msg = this->readAll();
emit socketRecived(msg);
}
}
TcpService::TcpService(const QHostAddress& addr, const int& port)
{
listen(addr, port);
}
TcpService::~TcpService()
{
{
std::lock_guard<std::mutex> lck(mConnectSocketMutex);
for (auto& it : mConnectSocket)
{
delete it.second;
}
}
}
void TcpService::slotSocketDisconnected(const qintptr& descriptor)
{
std::lock_guard<std::mutex> lck(mConnectSocketMutex);
auto it = mConnectSocket.find(descriptor);
if (mConnectSocket.end() != it)
{
delete it->second;
mConnectSocket.erase(descriptor);
}
}
void TcpService::slotDataRecived(const QByteArray& msg)
{
QString data = QString::fromUtf8(msg);
qDebug() << "service recv:" << data.toStdString().c_str();
}
void TcpService::incomingConnection(qintptr socketDescriptor)
{
TcpSocket* mTcpSocket = new TcpSocket;
connect(mTcpSocket, &TcpSocket::socketDisconnected, this, &TcpService::slotSocketDisconnected);
connect(mTcpSocket, &TcpSocket::socketRecived, this, &TcpService::slotDataRecived);
mTcpSocket->setSocketDescriptor(socketDescriptor);
{
std::lock_guard<std::mutex> lck(mConnectSocketMutex);
mConnectSocket[socketDescriptor] = mTcpSocket;
}
}
void TcpService::sendMsg(const char* msg, const qint64& len)
{
qint64 sendLen = 0;
std::lock_guard<std::mutex> lck(mConnectSocketMutex);
for (auto& it : mConnectSocket)
{
if (len != (sendLen = it.second->write(msg, len)))
{
qDebug() << "msg len:" << len << "\tsend len:" << sendLen << "\tsend failed!!";
}
}
}
tcpClient.h
#pragma once
#include <qtcpsocket.h>
#include <QHostAddress>
#include <QTcpSocket>
#include <QObject>
class TcpClient : public QTcpSocket
{
Q_OBJECT
public:
TcpClient(const QHostAddress& addr, const int& port);
virtual ~TcpClient(void) {};
protected slots:
virtual void slotConnected(void);
virtual void slotDisconnected(void);
virtual void slotDataReceived(void);
public:
/*
@brife 发送数据
@param data 发送的数据
@param len 数据长度
*/
virtual const bool sendMsg(const char* data, const uint32_t& len);
};
tcpClient.cpp
#include "tcpClient.h"
#include <QDebug>
#include <QByteArray>
#include <QString>
TcpClient::TcpClient(const QHostAddress& addr, const int& port)
{
connect(this, &QTcpSocket::connected, this, &TcpClient::slotConnected);
connect(this, &QTcpSocket::disconnected, this, &TcpClient::slotDisconnected);
connect(this, &QTcpSocket::readyRead, this, &TcpClient::slotDataReceived);
//连接服务器
this->connectToHost(addr, port);
}
void TcpClient::slotConnected(void)
{
qDebug() << "client connected!!";
}
void TcpClient::slotDisconnected(void)
{
qDebug() << "client disconnected!!";
}
void TcpClient::slotDataReceived(void)
{
if (0 < this->bytesAvailable())
{
QByteArray data;
data.resize(this->bytesAvailable());
this->read(data.data(), data.size());
QString msg = data.data();
qDebug() << "client recv:" << msg.toStdString().c_str();
}
}
const bool TcpClient::sendMsg(const char* data, const uint32_t& len)
{
return len == this->write(data, len);
}
main.cpp
#include <QtCore/QCoreApplication>
#include <QDebug>
#include <QTimer>
#include <QObject>
#include "QThread"
#include "tcpclient.h"
#include "tcpService.h"
namespace
{
//IP地址
#define HOST_ADDR QHostAddress::LocalHost
//端口
#define HOST_PORT 6666
class MyTcpService : public QTimer
{
private:
TcpService* mTcpService;
public:
MyTcpService(const QHostAddress& addr, const int& port)
{
mTcpService = new TcpService(addr, port);
connect(this, &QTimer::timeout, this, &MyTcpService::solveTimeout);
}
protected slots:
void solveTimeout(void)
{
QString msg("service msg");
mTcpService->sendMsg(msg.toStdString().c_str(), msg.size());
}
};
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//创建服务端
MyTcpService mTcpService(HOST_ADDR, HOST_PORT);
mTcpService.start(500);
//创建客户端
TcpClient mTcpClient(HOST_ADDR, HOST_PORT);
QString msg("client msg");
mTcpClient.sendMsg(msg.toStdString().c_str(), msg.size());
return a.exec();
}
执行结果
代码执行后,启动定时器向客户端发送数据,执行结果如下:
工程源码
源码环境使用VS2019+QT5.14开发,如果不能直接运行,可拷贝相关代码至正常环境运行。可点击工程源码链接获取工程源码。