基于Qt编写的文件传输工具

 更新时间:2024年12月12日 10:13:19   作者:codears  
这篇文章主要为大家详细介绍了如何基于Qt编写一个文件传输工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

文件传输工具

通过发送udp广播消息将IP广播给其他开启该程序的局域网机器

收到的广播消息可以显示在IP地址列表中,点击IP地址可以自动填充到IP地址栏内

选择文件后点击发送可以发送给指定IP,并能在传输过程中显示进度

默认端口6001。目前不支持修改,修改端口会导致网络连接失败。

界面比较简洁:

部分代码如下:

udp发送广播消息

void Client::SendUDPMsg() {
    int ret = 0;
    // 设置广播地址
    struct sockaddr_in client;
    memset(&client, 0, sizeof(client));
    client.sin_family = AF_INET;
    client.sin_port = htons(g_udpServerPort);
    client.sin_addr.s_addr = inet_addr("255.255.255.255");
    int len = sizeof(SOCKADDR);

    hostent* host = gethostbyname(g_serverHost.toStdString().c_str());
    QString msg = QString("broadcast|%1").arg(host->h_name);
    ret = sendto(m_udpClientSocket, msg.toStdString().c_str(), msg.length(), 0, (SOCKADDR*)&client, len);
}

udp接收消息:

void Client::RecvUDPMsg() {
    int ret = 0;
    struct sockaddr_in client;
    memset(&client, 0, sizeof(client));
    int len = sizeof(SOCKADDR);

    char buff[BUFF_SIZE] = {0};
    ret = recvfrom(m_udpServerSocket, buff, BUFF_SIZE, 0, (SOCKADDR*)&client, &len);
    QString host(inet_ntoa(client.sin_addr));
    if (m_localIPv4List.indexOf(host) == -1 && m_knownHosts.indexOf(host) == -1) {
        qDebug() << __FUNCTION__ << "new host:" << host;
        m_knownHosts.push_back(host);
        (static_cast<Work*>(m_pParent))->NewHost(host);
    } else {
        return;
    }
}

启动udp服务:

bool Client::StartUdpServer(NetworkParams& params) {
    QString host = params.serverIP;
    m_hostnm = gethostbyname(host.toStdString().c_str());
    if (m_hostnm != (struct hostent*)0) {
        qDebug() << __FUNCTION__ << "hostname:" << m_hostnm->h_addrtype << " addr:" << m_hostnm->h_name;
    }

    int ret = 0;
    if ((m_udpServerSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
        return false;
    }
    int port = params.serverPort;

    memset(&m_sockAddr, 0, sizeof(m_sockAddr));
    m_sockAddr.sin_family = AF_INET;
    m_sockAddr.sin_port = htons(port);
    //m_sockAddr.sin_addr.S_un.S_addr= inet_addr(host.toStdString().c_str());
    m_sockAddr.sin_addr.s_addr = INADDR_ANY;
    ret = bind(m_udpServerSocket, (const struct sockaddr*)&m_sockAddr, sizeof(m_sockAddr));
    if (ret < 0) {
        return false;
    } else {
    }

    GetIPv4List();
    return true;
}

启动tcp服务用于接收文件和发送文件:

bool Client::StartTcpServer(NetworkParams& params) {
    if (!m_bSocketClosed) {
        return true;
    }
    QString host = params.serverIP;
    m_hostnm = gethostbyname(host.toStdString().c_str());
    if (m_hostnm != (struct hostent*)0) {
        qDebug() << __FUNCTION__ << "hostname:" << m_hostnm->h_addrtype << " addr:" << m_hostnm->h_name;
    }

    int ret = 0;
    if ((m_tcpServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
        return false;
    }
    int port = params.serverPort;
    memset(&m_sockAddr, 0, sizeof(struct sockaddr_in));
    m_sockAddr.sin_family = AF_INET;
    m_sockAddr.sin_addr.s_addr = INADDR_ANY;
    m_sockAddr.sin_port = htons(port);
    ret = bind(m_tcpServerSocket, (const struct sockaddr*)&m_sockAddr, sizeof(m_sockAddr));
    if (ret < 0) {
        return false;
    } else {
        qDebug() << __FUNCTION__ << "bind success port:" << port;
    }

    if (listen(m_tcpServerSocket, 512)) {
        return false;
    }
    return true;
}

通过tcp发送文件:

bool Client::SendFile(QString strFullFilePath, QString strUserName) {
    if (strFullFilePath.isEmpty() || strUserName.isEmpty()) {
        return false;
    }
    strFullFilePath = strFullFilePath.replace("\\", "/");

    QString fileName = strFullFilePath.mid(strFullFilePath.lastIndexOf("/") + 1);
    QFile f(strFullFilePath);
    if (!f.exists()) {
        return false;
    }
    if (!f.open(QIODevice::ReadOnly)) {
        return false;
    }
    f.seek(SEEK_SET);
    quint64 fileSize = f.size();

    char chBuff[BUFF_SIZE] = {0};
    memset(chBuff, 0, BUFF_SIZE);

    QString s = QString("upload|%1|%2|%3|donotremove").arg(fileName).arg(fileSize).arg(strUserName);
    strcpy(chBuff, s.toStdString().c_str());
    send(m_iClientSocket, chBuff, strlen(chBuff) + 1, 0);

    quint64 sendSize = 0;
    NetworkParams params;
    params.totalSize = fileSize;
    while (sendSize < fileSize) {
        memset(chBuff, 0, BUFF_SIZE);
        qint64 iRead = f.read(chBuff, BUFF_SIZE);
        if (iRead < 0) {
            f.close();
            return false;
        }

        int iSend = send(m_iClientSocket, chBuff, iRead, 0);
        if (iSend < 0) {
            f.close();
            return false;
        }
        int temp = iRead;
        while (iSend < temp) {
            iSend = send(m_iClientSocket, chBuff + iSend, temp - iSend, 0);
            if (iSend < 0) {
                f.close();
                return false;
            }
            temp = temp - iSend;
        }

        sendSize += iSend;
        f.seek(sendSize);
        params.recved = sendSize;
        (static_cast<Work*>(m_pParent))->UpdateProgress(params);
    }

    f.close();
    closesocket(m_iClientSocket);
    m_bSocketClosed = true;
}

通过tcp接收文件:

bool Client::RecvFile() {
    SOCKET clientSock = NULL;
    struct sockaddr in_addr = {0};
    int addrLen = sizeof(in_addr);
    clientSock = accept(m_tcpServerSocket, (struct sockaddr*)&in_addr, &addrLen);

    if (clientSock == SOCKET_ERROR) {
        return false;
    }

    ssize_t len = 0;
    char buff[BUFF_SIZE] = {0};
    len = recv(clientSock, buff, sizeof(buff), 0);//1. get filename and client ip
    if (len <= 0) {
        return false;
    }

    QString fileNameAndClientIP(buff);//upload|filename|filesize|hostname
    QStringList sl = fileNameAndClientIP.split("|");
    if (sl.length() < 3) {
        return false;
    }

    QString fullFilePath = APPLICATION_DIR + "/" + sl.at(3);
    QDir d(fullFilePath);
    if (!d.exists()) {
        if (!d.mkdir(fullFilePath)) {
            ((Work*)m_pParent)->WarnMsg(QString("创建目录[%1]失败").arg(fullFilePath));
            return false;
        }
    }

    qlonglong fileSize = sl.at(2).toLongLong();
    QString fullName = fullFilePath + "/" + sl.at(1);
    QFile f(fullName);
    if (!f.open(QFile::ReadWrite)) {
        ((Work*)m_pParent)->WarnMsg(QString("打开文件:%1失败").arg(fullName));
        return false;
    }
    qlonglong recvLen = 0;
    NetworkParams params;
    params.totalSize = fileSize;
    while (recvLen < fileSize) {
        memset(buff, 0, sizeof(buff));
        len = recv(clientSock, buff, sizeof(buff), 0);
        if (len <= 0) {
            break;
        }
        recvLen += len;
        f.write(buff, len);
        params.recved = recvLen;
        (static_cast<Work*>(m_pParent))->UpdateProgress(params);
    }
    f.close();
    closesocket(clientSock);
    (static_cast<Work*>(m_pParent))->ReceivedFile(fullName);
}

以上就是基于Qt编写的文件传输工具的详细内容,更多关于Qt编写文件传输的资料请关注脚本之家其它相关文章!

相关文章

  • c++异常处理机制示例及详细讲解

    c++异常处理机制示例及详细讲解

    本篇文章主要是对c++异常处理机制示例进行了介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2014-02-02
  • C语言详解如何实现顺序栈

    C语言详解如何实现顺序栈

    顺序栈,就是用一组地址连续的存储单元来存放栈元素,然后用一个栈结构去维护一个栈。在C中,可用动态开辟的数组去表示,维护的栈结构需要有一个栈底和一个栈顶指针
    2022-04-04
  • C 语言二叉树几种遍历方法详解及实例

    C 语言二叉树几种遍历方法详解及实例

    这篇文章主要介绍了C 语言二叉树几种遍历方法详解及实例的相关资料,二叉树在数据结构当中是非常重要的知识要点,这里对二叉树进行了总结,需要的朋友可以参考下
    2017-01-01
  • C语言 全局变量和局部变量详解及实例

    C语言 全局变量和局部变量详解及实例

    这篇文章主要介绍了C语言 全局变量和局部变量详解及实例的相关资料,需要的朋友可以参考下
    2017-01-01
  • C语言实现链表贪吃蛇

    C语言实现链表贪吃蛇

    这篇文章主要为大家详细介绍了C语言实现链表贪吃蛇,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-06-06
  • C语言如何实现翻转字符串中的单词

    C语言如何实现翻转字符串中的单词

    这篇文章主要介绍了C语言如何实现翻转字符串中的单词,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • C++中新手容易犯的十种编程错误汇总

    C++中新手容易犯的十种编程错误汇总

    一段C语言代码,在编译、链接和运行的各个阶段都可能会出现问题,下面这篇文章主要给大家介绍了关于C++中新手容易犯的十种编程错误的相关资料,需要的朋友可以参考下
    2021-10-10
  • C++实现循环队列

    C++实现循环队列

    这篇文章主要为大家详细介绍了C++实现循环队列,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-01-01
  • C++ 自增自减运算符的实现示例

    C++ 自增自减运算符的实现示例

    本文主要介绍了C++ 自增自减运算符的实现示例,自增和自减运算符在C++中主要用于循环语句中,使循环变量的值自动+1或者-1,具有一定的参考价值,感兴趣的可以了解一下
    2023-08-08
  • C语言数据结构之栈和队列的实现及应用

    C语言数据结构之栈和队列的实现及应用

    栈和队列是一种数据结构,只规定了性质,并没有规定实现方式。本文将以顺序结构实现栈,链表方式实现队列,感兴趣的小伙伴快跟随小编一起学习一下吧
    2022-08-08

最新评论