基于Qt编写的文件传输工具
作者: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编写文件传输的资料请关注脚本之家其它相关文章!