• C++中UDP传输


    一. 程序说明
    1.本程序通过 UDP 来传输文件及其管理元数据(文件名、大小和日期等),包括client.cpp和server.cpp,分别是客户端程序和服务端程序。
    2.文件以二进制形式传输。
    3.由客户端指定文件目录,将文件传送到服务端,除了文件名之外,附带传送文件大小、创建时间等信息。
    4.获取文件大小和创建日期的详细程序可以看C++获取文件的创建时间和大小
    5.客户端发送完毕后,向服务端发送一条“end”信息,服务端受到后停止监听。

    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;
    }
    

      

      

    Copyright @WinkJie
  • 相关阅读:
    iview table的render()函数基本的用法
    【整理】iview Tree数据格式问题,无限递归树处理数据
    【整理】用JSON-server模拟REST API
    【整理】解决vue不相关组件之间的数据传递----vuex的学习笔记,解决报错this.$store.commit is not a function
    【整理】 vue-cli 打包后显示favicon.ico小图标
    【整理】treeGrid 树形表格
    【整理】iview中刷新页面的时候更新导航菜单的active-name
    [整理] webpack+vuecli打包生成资源相对引用路径与背景图片的正确引用
    在.vue文件中让html代码自动补全的方法(支持vscode)
    解决VSCode中使用vetur插件格式化vue文件时,js代码会自动加上冒号和分号
  • 原文地址:https://www.cnblogs.com/WinkJie/p/14350186.html
Copyright © 2020-2023  润新知