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

  

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM