1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > C++实现通过UDP传输文件

C++实现通过UDP传输文件

时间:2018-10-01 13:48:21

相关推荐

C++实现通过UDP传输文件

一. 程序说明

1.本程序通过 UDP 来传输文件及其管理元数据(文件名、大小和日期等),包括client.cpp和server.cpp,分别是客户端程序和服务端程序。

2.文件以二进制形式传输。

3.由客户端指定文件目录,将文件传送到服务端,除了文件名之外,附带传送文件大小、创建时间等信息。

4.获取文件大小和创建日期的详细程序可以看C++获取文件的创建时间和大小

5.客户端发送完毕后,向服务端发送一条“end”信息,服务端受到后停止监听。

6.通过UDP传输比TCP快,但是UDP不如TCP稳定,可能出现丢包和乱序的情况。这里通过“发-收-发”的方式防止丢包和乱序,即客户端每发送一条消息,服务端收到后都会回信一条,受到回信后,客户端再继续发送,没有受到则报错。还有一种实现方式是,利用多线程发送信息,给每次发送的信息编号,服务端检查收到的信息的编号,以此判断是否出现乱序或丢包。(暂未完成)

二. 代码实现

client.cpp:

/*

客户端程序

客户端给服务端发送文件,包含管理元数据(文件名、大小和日期)

*/

#include<iostream>

#include<WinSock2.h>

#include<winsock.h>

#include<Windows.h>

#include<string>

#include<cstring>

#include <fstream>

#include <io.h>

#pragma comment(lib,"ws2_32.lib")

#define BUF_SIZE 1024

#define SERVER_ID "127.0.0.1"

#define PATH_LENGTH 20

using namespace std;

char sendBuff[BUF_SIZE];

char recvBuff[BUF_SIZE];

char fileName[PATH_LENGTH];

BOOL getFileTime(HANDLE hFile, LPSTR lpszCreationTime)//获取文件创建日期

{

FILETIME ftCreate, ftAccess, ftWrite;

SYSTEMTIME stUTC1, stLocal1;

// -------->获取 FileTime

if (!GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite)) {

cout << "error!" << endl;

return FALSE;

}

//---------> 转换: FileTime --> LocalTime

FileTimeToSystemTime(&ftCreate, &stUTC1);

SystemTimeToTzSpecificLocalTime(NULL, &stUTC1, &stLocal1);

// ---------> Show the date and time.

sprintf(lpszCreationTime, "%02d/%02d/%02d %02d:%02d",

stLocal1.wYear, stLocal1.wMonth, stLocal1.wDay,

stLocal1.wHour, stLocal1.wMinute);

return TRUE;

}

int main() {

WSADATA wsa;

if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {

cout << "Initialization failed." << endl;

return -1;

}

SOCKET client = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

if (client == -1) {

cout << "Socket failed." << endl;

return -1;

}

sockaddr_in sadr;

sadr.sin_family = AF_INET;

sadr.sin_port = htons(5000);

sadr.sin_addr.S_un.S_addr = inet_addr(SERVER_ID);

int nAddrlen = sizeof(sadr);

while (true) {

cout << "---------------------SENDING...---------------------" << endl;

cout << "Please input the filename: " << endl;

cin >> fileName;

FILE *fp;

if (!(fp = fopen(fileName, "rb"))) {

cout << "Fail to open file." << endl;

continue;

}

//先传送文件名

sendto(client, fileName, strlen(fileName), 0, (sockaddr*)&sadr, sizeof(sadr));

int length;

int ret;

while ((length = fread(sendBuff, 1, BUF_SIZE, fp)) > 0) {

ret = sendto(client, sendBuff, length, 0, (sockaddr*)&sadr, sizeof(sadr));

if (!ret) {

cout << "An error occurred while sending." << endl;

return -1;

}

ret = recvfrom(client, recvBuff, BUF_SIZE, 0, (sockaddr*)&sadr, &nAddrlen);

if (!ret) {

cout << "Fail to receive." << endl;

return -1;

}

else {

if (strcmp(recvBuff, "success")) {

cout << "Fail to receive." << endl;

return -1;

}

}

}

//传送文件发送结束信息

char end_flag[10] = "end";

ret = sendto(client, end_flag, length, 0, (sockaddr*)&sadr, sizeof(sadr));

//获取文件创建时间和大小

HANDLE hFile;

TCHAR szCreationTime[30];

hFile = CreateFile(fileName, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

getFileTime(hFile, szCreationTime);

if (hFile == INVALID_HANDLE_VALUE) {

cout << "error!" << endl;

return -1;

}

int size = GetFileSize(hFile, NULL);

//传送时间和大小信息

ret = sendto(client, szCreationTime, 30, 0, (sockaddr*)&sadr, sizeof(sadr));

size = size / 1024 + 1;//B转KB

string tempSize = to_string(size);

tempSize += "KB";

char fileSize[20];

strcpy(fileSize, tempSize.c_str());

ret = sendto(client, fileSize, 20, 0, (sockaddr*)&sadr, sizeof(sadr));

cout << "successfully sent!" << endl;

fclose(fp);

CloseHandle(hFile);

}

closesocket(client);

WSACleanup();

return 0;

}

server.cpp:

/*

服务端程序

接收从客户端发送的文件,包含管理元数据(文件名、大小和日期)

*/

#include<iostream>

#include<WinSock2.h>

#include<winsock.h>

#pragma comment(lib,"ws2_32.lib")

#define BUF_SIZE 1024

#define PATH_LENGTH 20

using namespace std;

char sendBuff[BUF_SIZE];

char recvBuff[BUF_SIZE];

char fileName[PATH_LENGTH];

int main() {

WSADATA wsa;

if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {

cout << "Initialization failed." << endl;

return -1;

}

SOCKET server = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

if (server == -1) {

cout << "Socket failed." << endl;

return -1;

}

sockaddr_in my_addr, remote_addr;

int nAddrlen = sizeof(remote_addr);

my_addr.sin_family = AF_INET;

my_addr.sin_port = htons(5000);

my_addr.sin_addr.S_un.S_addr = INADDR_ANY;

if (::bind(server, (sockaddr*)&my_addr, sizeof(my_addr)) == SOCKET_ERROR) {

cout << "Bind error!" << endl;

return -1;

}

while (true) {

cout << "---------------------RECEIVING...---------------------" << endl;

//接收文件名

int ret = recvfrom(server, fileName, BUF_SIZE, 0, (sockaddr*)&remote_addr, &nAddrlen);

cout << "Filename: " << fileName << endl;

errno_t err;

FILE *fp;

if ((err = fopen_s(&fp, fileName, "wb")) < 0) {

cout << "Create failed." << endl;

return -1;

}

int length;

while ((length = recvfrom(server, recvBuff, BUF_SIZE, 0, (sockaddr*)&remote_addr, &nAddrlen))) {

if (!strcmp(recvBuff, "end"))//接收结束信息

break;

if (length == 0) {

cout << "An error occurred while receiving." << endl;

return -1;

}

int ret = fwrite(recvBuff, 1, length, fp);

if (ret < length) {

cout << "Write failed." << endl;

return -1;

}

sendto(server, "success", sizeof("success") + 1, 0, (SOCKADDR*)&remote_addr, sizeof(remote_addr));

}

//接收文件创建日期、大小信息

char creationTime[30];

char fileSize[20];

recvfrom(server, creationTime, 30, 0, (sockaddr*)&remote_addr, &nAddrlen);

recvfrom(server, fileSize, 20, 0, (sockaddr*)&remote_addr, &nAddrlen);

cout << "Creation Time:" << creationTime << endl;

cout << "Size:" << fileSize << endl;

cout << "Successfully received!" << endl;

fclose(fp);

}

closesocket(server);

WSACleanup();

return 0;

}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。