我用TCP发送文件,但是发送的时候界面就会卡死,求解决!

mingxinke 2014-10-30 11:38:38
代码如下,这是书上的一个TCP发送文件的例子,但是没有解决界面卡死不动的问题。
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);

loadSize = 4*1024;
totalBytes = 0;
bytesWrinten = 0;
bytesToWrite = 0;
tcpClient = new QTcpSocket(this);
connect(tcpClient,SIGNAL(connected()),this,SLOT(startTransfer()) );
//当连接成功时发送connected()信号,我们开始传文件
connect(tcpClient,SIGNAL(bytesWritten(qint64)),this,SLOT(updataClientProgress(qint64)) );
//当有数据发送时,就更新进度条
connect(tcpClient,SIGNAL(error(QAbstractSocket::SocketError)),this
,SLOT(displayError(QAbstractSocket::SocketError)) );
//当出错时,显示出错信息
ui->sendButton->setEnabled(false);
//开始使发送不可用
}

Widget::~Widget()
{
delete ui;
}

void Widget::openFile()
{
qDebug() << "openFile()" << endl;
fileName = QFileDialog::getOpenFileName(this);
if(!fileName.isEmpty())
{
ui->sendButton->setEnabled(true);
ui->clientStatusLabel->setText(tr("打开文件%1成功").arg(fileName));
}

}

void Widget::on_openButton_clicked()
{
openFile();
}

void Widget::send() //连接服务器
{
qDebug() << "send()" << endl;
ui->sendButton->setEnabled(false);
bytesWrinten = 0; //初始化已发送字节为0
ui->clientStatusLabel->setText(tr("正在连接c..."));
tcpClient->connectToHost(ui->hostLineEdit->text(),
ui->portLineEdit->text().toInt()); //连接

}

void Widget::startTransfer() //实现文件大小等信息的发送
{
qDebug() << "startTransfer()" << endl;
localFile = new QFile(fileName);
if(!localFile->open(QFile::ReadOnly))
{
qDebug()<<"open file error!";
return;
}
totalBytes = localFile->size();
//文件总大小
QDataStream sendOut(&outBlock,QIODevice::WriteOnly);
sendOut.setVersion(QDataStream::Qt_5_3);
QString currentFileName = fileName.right(fileName.size() -
fileName.lastIndexOf('/')-1);
sendOut << qint64(0) << qint64(0) << currentFileName;
//这里总大小是总大小信息、文件大小信息、文件名和实际文件大小的总和
totalBytes += outBlock.size();
sendOut.device()->seek(0);

//返回outBolock的开始,用实际的大小信息代替两个qint64(0)空间
sendOut<<totalBytes<<qint64((outBlock.size() - sizeof(qint64)*2));
//发送完头数据后剩余数据的大小
bytesToWrite = totalBytes - tcpClient->write(outBlock);
ui->clientStatusLabel->setText(tr("已连接!"));
outBlock.resize(0);
}

//更新进度条,实现文件的传送
void Widget::updataClientProgress(qint64 numBytes)
{
qDebug() << "updataClientProgress()" << endl;
bytesWrinten += (int)numBytes;
//已经发送数据的大小
if(bytesToWrite > 0) //如果已经发送了数据
{
outBlock = localFile->read(qMin(bytesToWrite,loadSize));
//每次发送loadSize 大小的数据,这里设置为4KB,如果剩余的数据不足4KB
//就发送剩余数据的大小
bytesToWrite -= (int)tcpClient->write(outBlock);
//发送完一次数据后还剩余数据的大小
outBlock.resize(0);
//清空发送缓冲区
}
else
{
localFile->close();//如果没有发送任何数据,则关闭文件

}
ui->clientprogressBar->setMaximum(totalBytes);
ui->clientprogressBar->setValue(bytesWrinten);
//更新进度条
if(bytesWrinten == totalBytes) //发送完毕
{
ui->clientStatusLabel->setText(tr("发送文件 %1 成功!").arg(fileName));
localFile->close();
tcpClient->close();
}
}

//显示错误
void Widget::displayError(QAbstractSocket::SocketError)
{
qDebug() << "displayError()" << endl;
qDebug() << tcpClient->errorString();
tcpClient->close();
ui->clientprogressBar->reset();
ui->clientStatusLabel->setText(tr("Client Ready"));
ui->sendButton->setEnabled(true);

}

void Widget::on_sendButton_clicked()
{
qDebug() << "on_sendButton_clicked()" << endl;
send();
}
...全文
1435 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
feiyangbaxia 2014-12-10
  • 打赏
  • 举报
回复
往上贴程序有点麻烦,建议看一下 郑阿奇 主编的《Qt 4 开发实践》那上面有例子,比较容易看懂的,我也是初学者。
翅膀又硬了 2014-12-10
  • 打赏
  • 举报
回复
引用 5 楼 mingxinke 的回复:
[quote=引用 4 楼 Marcelxx 的回复:] [quote=引用 3 楼 mingxinke 的回复:] [quote=引用 1 楼 Marcelxx 的回复:] 发送的时候,发送文件,发送的信息太大,可能阻塞在那里,建议你写成多线程。同样,连接服务器的那个地方也写到多线程里面去。比如服务器不在线的时候,连接服务器的那个地方也可能会阻塞在那里,也会卡死。
我刚学的,多线程不怎么会用,你能和我仔细的讲一下吗?最好帮我加一下多线程的代码,跪求大神![/quote] 多线程只是概念和运行的区别,编码和这些没多大区别,注意下同步和互斥就行了。 QThread这个类你晓得噻,继承QThread这个类,在里面创建套接字就行了,这样收发就不会导致界面阻塞了。 你百度下qt多线程,写几个简单地多线程程序,了解下运行机制就行了。Qt的多线程封装得很好,很方便使用。在多线程中,使用信号和槽与主界面进行通信。[/quote] 不是只有run()函数里的才是在另一个线程运行吗?那么多函数怎么都放在run()函数里?我刚才看了一下多线程,例子都很简单,还不是很明白怎么写才能解决这个问题。你有相似的例子吗?发给我学习学习,我的邮箱745688760@qq.com,谢谢大神![/quote] 你把发送的代码直接放到run函数里面。在原来的需要发送的地方,调用一下start(),就行了。
xy2163com 2014-12-09
  • 打赏
  • 举报
回复
QTcpSocket、QTcpServer默认是异步的,只要你不用waitForConnected、waitForRead之类的同步函数;所以你应该看看是不是由于读取大文件导致了主线程阻塞,主线程阻塞又造成界面无法刷新,从而出现界面卡现象
mingxinke 2014-11-26
  • 打赏
  • 举报
回复
引用 8 楼 fqj2008 的回复:
楼上已经告诉你思路啦,我来告诉你解决多线,给我点分就行。用 object.MoveTothread()不会就留言给我
你可以和我说说吗?我的QQ745688760,谢谢!
woshiwuhanren 2014-11-01
  • 打赏
  • 举报
回复
原因很复杂 先测试
fqj2008 2014-11-01
  • 打赏
  • 举报
回复
楼上已经告诉你思路啦,我来告诉你解决多线,给我点分就行。用 object.MoveTothread()不会就留言给我
mingxinke 2014-10-31
  • 打赏
  • 举报
回复
引用 6 楼 qwer_boo 的回复:
多线程的例子网上很多的,嗖一下~就有了
但是都没有能解决这个问题的,有点束手无策了!本人刚学,很多都不懂!
qwer_boo 2014-10-31
  • 打赏
  • 举报
回复
多线程的例子网上很多的,嗖一下~就有了
mingxinke 2014-10-30
  • 打赏
  • 举报
回复
引用 4 楼 Marcelxx 的回复:
[quote=引用 3 楼 mingxinke 的回复:] [quote=引用 1 楼 Marcelxx 的回复:] 发送的时候,发送文件,发送的信息太大,可能阻塞在那里,建议你写成多线程。同样,连接服务器的那个地方也写到多线程里面去。比如服务器不在线的时候,连接服务器的那个地方也可能会阻塞在那里,也会卡死。
我刚学的,多线程不怎么会用,你能和我仔细的讲一下吗?最好帮我加一下多线程的代码,跪求大神![/quote] 多线程只是概念和运行的区别,编码和这些没多大区别,注意下同步和互斥就行了。 QThread这个类你晓得噻,继承QThread这个类,在里面创建套接字就行了,这样收发就不会导致界面阻塞了。 你百度下qt多线程,写几个简单地多线程程序,了解下运行机制就行了。Qt的多线程封装得很好,很方便使用。在多线程中,使用信号和槽与主界面进行通信。[/quote] 不是只有run()函数里的才是在另一个线程运行吗?那么多函数怎么都放在run()函数里?我刚才看了一下多线程,例子都很简单,还不是很明白怎么写才能解决这个问题。你有相似的例子吗?发给我学习学习,我的邮箱745688760@qq.com,谢谢大神!
Marcelxx 2014-10-30
  • 打赏
  • 举报
回复
引用 3 楼 mingxinke 的回复:
[quote=引用 1 楼 Marcelxx 的回复:] 发送的时候,发送文件,发送的信息太大,可能阻塞在那里,建议你写成多线程。同样,连接服务器的那个地方也写到多线程里面去。比如服务器不在线的时候,连接服务器的那个地方也可能会阻塞在那里,也会卡死。
我刚学的,多线程不怎么会用,你能和我仔细的讲一下吗?最好帮我加一下多线程的代码,跪求大神![/quote] 多线程只是概念和运行的区别,编码和这些没多大区别,注意下同步和互斥就行了。 QThread这个类你晓得噻,继承QThread这个类,在里面创建套接字就行了,这样收发就不会导致界面阻塞了。 你百度下qt多线程,写几个简单地多线程程序,了解下运行机制就行了。Qt的多线程封装得很好,很方便使用。在多线程中,使用信号和槽与主界面进行通信。
mingxinke 2014-10-30
  • 打赏
  • 举报
回复
引用 1 楼 Marcelxx 的回复:
发送的时候,发送文件,发送的信息太大,可能阻塞在那里,建议你写成多线程。同样,连接服务器的那个地方也写到多线程里面去。比如服务器不在线的时候,连接服务器的那个地方也可能会阻塞在那里,也会卡死。
我刚学的,多线程不怎么会用,你能和我仔细的讲一下吗?最好帮我加一下多线程的代码,跪求大神!
柳11 2014-10-30
  • 打赏
  • 举报
回复
多线程耶,只要不要在次线程中操作界面控件就行了。
Marcelxx 2014-10-30
  • 打赏
  • 举报
回复
发送的时候,发送文件,发送的信息太大,可能阻塞在那里,建议你写成多线程。同样,连接服务器的那个地方也写到多线程里面去。比如服务器不在线的时候,连接服务器的那个地方也可能会阻塞在那里,也会卡死。

16,216

社区成员

发帖
与我相关
我的任务
社区描述
Qt 是一个跨平台应用程序框架。通过使用 Qt,您可以一次性开发应用程序和用户界面,然后将其部署到多个桌面和嵌入式操作系统,而无需重复编写源代码。
社区管理员
  • Qt
  • 亭台六七座
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧