Qt编写的文件传输工具

使用QT编写的文件传输工具

文件传输工具

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

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

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

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

资源链接:https://download.csdn.net/download/codears/90117330?spm=1001.2014.3001.5503

界面比较简洁:

部分代码如下:

udp发送广播消息

cpp 复制代码
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接收消息:

cpp 复制代码
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服务:

cpp 复制代码
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服务用于接收文件和发送文件:

cpp 复制代码
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发送文件:

cpp 复制代码
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接收文件:

cpp 复制代码
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);
}
相关推荐
C++ 老炮儿的技术栈2 小时前
从 Qt Designer 属性编辑器的层级可以看到继承链
c语言·数据库·c++·qt·sqlite·visual studio
new_zhou3 小时前
C++ 项目 AI 协作指南(Windows / MSVC 环境)
c++·人工智能·windows
水饺编程4 小时前
AT&T 汇编语言学习笔记开篇语
c语言·汇编·c++
Iruoyaoxh4 小时前
类和对象~
开发语言·c++
程序喵大人4 小时前
【C++进阶】STL算法与函数对象 - 04 find、count和any_of把查询写成意图
开发语言·c++·算法
豆沙沙包?4 小时前
c++中引用(P7-P11)
java·c++·算法
wuminyu5 小时前
虚拟线程底层ForkJoinPool的工作窃取算法机制
java·linux·c语言·jvm·c++
我是小灰灰吖5 小时前
Ubuntu 22.04 + Qt 6.9.3 应用程序打包与部署完整指南
qt·ubuntu
吹什么轩5 小时前
c++复习:c++11:lambda表达式
开发语言·c++
不会代码的小猴5 小时前
标准模板库(STL)
开发语言·c++·笔记·算法