当前位置: 代码迷 >> QT开发 >> 小弟我用TCP发送文件,但是发送的时候界面就会卡死,求解决
  详细解决方案

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

热度:157   发布时间:2016-04-25 03:06:06.0
我用TCP发送文件,但是发送的时候界面就会卡死,求解决!
代码如下,这是书上的一个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();
}

------解决思路----------------------
发送的时候,发送文件,发送的信息太大,可能阻塞在那里,建议你写成多线程。同样,连接服务器的那个地方也写到多线程里面去。比如服务器不在线的时候,连接服务器的那个地方也可能会阻塞在那里,也会卡死。
------解决思路----------------------
引用:
Quote: 引用:

发送的时候,发送文件,发送的信息太大,可能阻塞在那里,建议你写成多线程。同样,连接服务器的那个地方也写到多线程里面去。比如服务器不在线的时候,连接服务器的那个地方也可能会阻塞在那里,也会卡死。

我刚学的,多线程不怎么会用,你能和我仔细的讲一下吗?最好帮我加一下多线程的代码,跪求大神!

多线程只是概念和运行的区别,编码和这些没多大区别,注意下同步和互斥就行了。
QThread这个类你晓得噻,继承QThread这个类,在里面创建套接字就行了,这样收发就不会导致界面阻塞了。
你百度下qt多线程,写几个简单地多线程程序,了解下运行机制就行了。Qt的多线程封装得很好,很方便使用。在多线程中,使用信号和槽与主界面进行通信。
------解决思路----------------------
楼上已经告诉你思路啦,我来告诉你解决多线,给我点分就行。用 object.MoveTothread()不会就留言给我
------解决思路----------------------
引用:
Quote: 引用:

Quote: 引用:

Quote: 引用:

发送的时候,发送文件,发送的信息太大,可能阻塞在那里,建议你写成多线程。同样,连接服务器的那个地方也写到多线程里面去。比如服务器不在线的时候,连接服务器的那个地方也可能会阻塞在那里,也会卡死。

我刚学的,多线程不怎么会用,你能和我仔细的讲一下吗?最好帮我加一下多线程的代码,跪求大神!

多线程只是概念和运行的区别,编码和这些没多大区别,注意下同步和互斥就行了。
QThread这个类你晓得噻,继承QThread这个类,在里面创建套接字就行了,这样收发就不会导致界面阻塞了。
你百度下qt多线程,写几个简单地多线程程序,了解下运行机制就行了。Qt的多线程封装得很好,很方便使用。在多线程中,使用信号和槽与主界面进行通信。

不是只有run()函数里的才是在另一个线程运行吗?那么多函数怎么都放在run()函数里?我刚才看了一下多线程,例子都很简单,还不是很明白怎么写才能解决这个问题。你有相似的例子吗?发给我学习学习,我的邮箱745688760@qq.com,谢谢大神!


你把发送的代码直接放到run函数里面。在原来的需要发送的地方,调用一下start(),就行了。
------解决思路----------------------
往上贴程序有点麻烦,建议看一下 郑阿奇 主编的《Qt 4 开发实践》那上面有例子,比较容易看懂的,我也是初学者。
  相关解决方案