使用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);
}