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);
}
相关推荐
天堂的恶魔94633 分钟前
QT —— 信号和槽(槽函数)
开发语言·qt
weixin_4450547244 分钟前
力扣刷题-热题100题-第35题(c++、python)
c++·python·leetcode
XXYBMOOO1 小时前
基于 Qt 的 BMP 图像数据存取至 SQLite 数据库的实现
数据库·c++·qt
虾球xz2 小时前
游戏引擎学习第230天
c++·学习·游戏引擎
不知道叫什么呀4 小时前
【C语言基础】C++ 中的 `vector` 及其 C 语言实现详解
c语言·开发语言·c++
汇太浪4 小时前
第十六届蓝桥杯大赛软件赛省赛 C++ 大学 B 组 部分题解
c++·蓝桥杯
WW_千谷山4_sch4 小时前
MYOJ_11700(UVA10591)Happy Number(快乐数)(超快解法:图论思想解题)
c++·算法
郭涤生5 小时前
QML 信号与槽
c++·笔记·qt
DreamLife☼5 小时前
QtApplets-实现应用程序单例模式,防止重复运行
qt·单例模式·跨平台·进程管理·qlockfile
Ethon_王5 小时前
C++ STL deque容器详解
c++