在QTTCP协议实现多线程的传输文件
目录
本文在QT中利用TCP协议实现了一个多线程的文件互传系统,其中遇到了不少槽点,甚至还有很多亟待解决的问题,因此想写一篇博文来记录一下。
一、主要功能
- 服务器端显示在线的客户端列表
因为运用了多线程,所以可以支持多个客户端同时登陆,服务器主界面也不会陷入假死状态。
- 服务器端可指定某一用户进行文件发送
鼠标选中后,进行发送即可。
- 所有在线客户端可以同时对服务器端进行发送文件的操作
二、基于QT的TCP套接字通信
1.服务器端通信流程
(1)创建一个TCP服务器对象
我这里是新建了一个myTcpServer的类,该类继承自QTcpServer。
-
-
-
-
-
-
class myTcpServer : public QTcpServer
-
{
-
Q_OBJECT
-
public:
-
explicit myTcpServer(QObject *parent = nullptr);
-
-
protected:
-
void incomingConnection(qintptr handle) override;
-
-
signals:
-
void sendDescriptor(qintptr handle);
-
-
public slots:
-
-
};
-
-
(2)实例化myTcpServer对象,并对服务器的IP和端口设置监听
-
//实例化myTcpServer对象,用重写incomingConnection的方式获取通讯socket
-
m_serverRecv = new myTcpServer(this);
-
m_serverSend = new myTcpServer(this);
-
//设置监听ip和端口
-
m_serverRecv->listen(QHostAddress::AnyIPv4,port);
-
m_serverSend->listen(QHostAddress::AnyIPv4,port);
(3)在myTcpServer中重写incomingConnection函数
每当有新连接的时候,会自动触发该函数,并获得一个与该连接通信的描述符。
-
-
-
myTcpServer::myTcpServer(QObject *parent) : QTcpServer(parent)
-
{
-
-
}
-
-
//创建一个class,并继承qtcpserver,重写其中的incomingConnection函数,每当有新连接时执行下面的函数
-
void myTcpServer::incomingConnection(qintptr handle)
-
{
-
//给主线程发送一个信号,并传递描述符
-
emit sendDescriptor(handle);
-
}
(4)创建通信套接字对象(QTcpSocket)
创建一个通信套接字对象(QTcpSocket),并将上面获得的描述符写入。
-
//创建套接字
-
m_socket = new QTcpSocket;
-
//写入描述符
-
m_socket->setSocketDescriptor(handle);
(5)利用通信套接字对象和客户端进行数据传输
-
//读
-
fileData = m_socket->read(65536);
-
//写
-
m_socket->write((char*)&fileNameSize,4);
2.客户端通信流程
(1)创建通信的套接字类 QTcpSocket 对象
(2)绑定和连接服务器的IP地址和端口
-
//创建套接字
-
m_socket = new QTcpSocket;
-
//绑定和连接
-
m_socket->connectToHost(QHostAddress(ip),port);
(3)利用通信套接字对象和客户端进行数据传输
三、基于QT的多线程
1.创建流程
(1)创建一个工作类,继承QObject,将线程函数写在public中
(2)实例化工作类和线程
注意工作类不要指定父组件。
-
//实例化一个发送文件的工作类
-
sendWork* sendWorker = new sendWork;
-
//实例化一个发送线程
-
m_sendThread = new QThread;
(3)将工作类移入线程中,启动线程
-
//将工作类挪入线程中
-
sendWorker->moveToThread(m_sendThread);
-
//启动线程
-
m_sendThread->start();
(4)用信号槽在主线程激活子线程的线程函数
注意不要在主线程直接调用线程函数,一定要用信号槽,否则函数依然在主线程中执行
-
//连接子线程的工作函数
-
connect(this,&MainWindow::sendStart,sendWorker,&sendWork::sendFiles);
-
//发射信号激活工作函数并传递通信描述符
-
emit sendStart(handle);
四、源码
源码放在这里了,0积分,有需要请大家自取
五、踩坑记录
- 不要在线程间传递QTcpSocket套接字对象,如果想在子线程中进行传输,一定不要在主线程中创建套接字后,再通过其它方式传入子线程,这样会导致不可预知的错误,一定要在你使用的子线程里创建对象。
- 使用readyread信号判断有没有数据输入时,要注意不是对方调用几次write,就会来几次readyread,有可能write次数较快,readyread信号会重叠在一起。建议用bytesAvailable()获取缓存内还未读取的字节数,然后两者一起配合使用
- 本文在服务器端接收数据和发送数据分别使用了两个端口,本身考虑使用一个端口,但是在数据收发时会有触发不了readyread信号的情况产生。
- 在使用多线程进行数据收发时,用信号槽触发工作函数,如果不在信号激活后马上进行disconnect,有可能会导致一个信号多次触发工作函数。
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgcback
系列文章
更多
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01