一. 程序说明
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;
}

C++实现通过UDP传输文件相关推荐

  1. java udp传输文件_JAVA使用UDP收发文件

    java使用UDP发送文件 环境 maven 3.6 jdk 1.8 udp-nio 分支支持批量发送 服务端源码(接收文件) package com.banywl.file.transfer.udp ...

  2. python udp 传输文件_python网络编程:UDP方式传输数据

    UDP --- 用户数据报协议(User Datagram Protocol),是一个无连接的简单的面向数据报的运输层协议. UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能 ...

  3. udp 传输文件 java_Java 网络编程 之 UDP 文件传输

    服务器端 package com.udp; import java.io.File; import java.io.FileOutputStream; import java.io.IOExcepti ...

  4. node.js 实现udp传输_Node.js实战15:通过udp传输文件。

    本文将要写一个udp服务器,和一个udp客户端,并实现客户端发送文件给服务器. 服务器端 代码如下:var dgram = require("dgram"); server(); ...

  5. linux nc传输目录文件,linux nc 命令传输文件

    一个更有用的轻量级工具,nc的另一个强大的功能---文件传输. AME nc - arbitrary TCP and UDP connections and listens SYNOPSIS nc [ ...

  6. Socket异步服务器,可以监控客户端的状态,功能有,文字测试,服务端向客户端传输屏幕录像(UDP传输)、监控客户端屏幕(UDP传输),抖动用户窗体、发送文件给用户、扫描客户的C盘目录。

    用VS2015工具C#语言编写了一个简单的Socket异步服务器,可以监控客户端的状态,功能有,文字测试,服务端向客户端传输屏幕录像(UDP传输).监控客户端屏幕(UDP传输),抖动用户窗体.发送文件 ...

  7. 浅析C#UDP传输大文件

    1.前言 众所周知,UDP通信是允许丢包的,这个通信方式本身就是"不太靠谱的",针对的是即便数据丢了几包也无所谓的情景,如果你非要用这个传输大文件(如一个视频),我只能说你和我一样 ...

  8. linux 指令tftp传输文件_Linux tftp 命令用法详解-Linux命令大全(手册)

    tftp 在本机和tftp服务器之间使用TFTP协议传输文件 补充说明 tftp命令 用在本机和tftp服务器之间使用TFTP协议传输文件. TFTP是用来下载远程文件的最简单网络协议,它其于UDP协 ...

  9. linux 指令tftp传输文件_Linux tftp命令使用详解:在本机与tftp服务器之间使用TFTP协议传输文件...

    tftp命令用在本机和tftp服务器之间使用TFTP协议传输文件. TFTP是用来下载远程文件的最简单网络协议,它其于UDP协议而实现.嵌入式linux的tftp开发环境包括两个方面:一是linux服 ...

最新文章

  1. 条件编译用法(#ifndef #define #endif#else)
  2. PHP实现RPC(简版)
  3. Vue 监视属性 watch
  4. Cocos2d-x 3 X CMake MinGW版本编译运行
  5. 不同苹果账号体系的Capabilities情况
  6. 对话阿里 CTO 程立:未来数字世界的根基是开源和云
  7. 软件工程期末复习汇总
  8. OOP的核心思想是什么?
  9. RiceQuant开源框架RQAlpha阅读笔记(转)
  10. 使用安卓模拟器+Xposed+JustTrustMe+burp suite抓取app的https流量
  11. python面向对象练习题
  12. Alpha、Beta、RC、GA版本的区别
  13. E-mail营销介绍
  14. 歌曲光辉岁月和弦走向探究
  15. 【NG-ZORRO、Angular】日期选择框时间段nz-range-picker设置开始结束时间00:00:00~23:59:59
  16. html5语义化标签及优点
  17. AcWing 198. [HAOI2007] 反素数 约数个数+dfs
  18. 世事洞明皆学问,人情练达即文章
  19. Swing中滚动面板JScrollPanede使用
  20. MacBook通过MacBook安装Windows系统出现“下载windows支持软件时未能储存到所选驱动器” 折中方案

热门文章

  1. linux修改密码提示unix,linux中普通用户批改密码出现(passwd:Authentication token manipulation error)...
  2. mysql 重试_重试MySQL/SQLAlchemy的死锁
  3. android域账号认证失败,绕过域账户认证失败锁定次数限制的技巧
  4. linux执行class文件_深入理解linux内核——可执行文件执行过程(2)
  5. linux刷除U盘grub,删除linux系统出现grub rescue
  6. python大数据项目_(价值1280)大数据项目实战之Python金融应用编程
  7. 在C语言中malloc怎么声明,问下关于malloc的声明问题
  8. 基于 xilinx vivado 的PCIE ip核设置与例程代码详解
  9. 手机桌面隐藏大师_应用加密,教你一招隐藏手机桌面上的软件!
  10. java上传音频到服务器_Java 客户端向服务端上传mp3文件数据的实例代码