Member 13123405 Ответов: 2

Как заставить клиента отправлять много файлов изображений (. jpg) вместе на сервер в C++ с помощью winsock


Я использую Visual Studio Ultimate 2013.

Я разработал простое клиентское и серверное приложение с использованием winsock API на C++, где клиент отправляет приветственное сообщение серверу. Но я хочу отправить несколько изображений на сервер сразу из клиентского сокета. Я не знаю, как отправлять файлы изображений с помощью программирования сокетов. Пожалуйста, помогите мне с отправкой нескольких файлов изображений одновременно с помощью winsock.

Мой код выглядит следующим образом:

Что я уже пробовал:

Клиент:
#include <iostream>
#include <winsock2.h>

using namespace std;

#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")

static void ClientApp()
{
    WSADATA WSAData;
    SOCKET server;
    SOCKADDR_IN addr;

    WSAStartup(MAKEWORD(2, 0), &WSAData);
    server = socket(AF_INET, SOCK_STREAM, 0);

    addr.sin_addr.s_addr = inet_addr("192.168.100.4");
    addr.sin_family = AF_INET;
    addr.sin_port = htons(5555);

    connect(server, (SOCKADDR *)&addr, sizeof(addr));
    cout << "Connected to server!" << endl;

    char buffer[1024] = { 'h', 'e', 'l', 'l', 'o', '.' };
    send(server, buffer, sizeof(buffer), 0);
    cout << "Message sent!" << endl;

    closesocket(server);
    WSACleanup();
    cout << "Socket closed." << endl << endl;
}

int main()
{
    ClientApp();
}



Сервер:
#include <iostream>
#include <winsock2.h>

using namespace std;

#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")

static void ServerApp()
{
    WSADATA WSAData;

    SOCKET server, client;

    SOCKADDR_IN serverAddr, clientAddr;

    WSAStartup(MAKEWORD(2, 0), &WSAData);
    server = socket(AF_INET, SOCK_STREAM, 0);

    serverAddr.sin_addr.s_addr = INADDR_ANY;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(5555);

    bind(server, (SOCKADDR *)&serverAddr, sizeof(serverAddr));
    listen(server, 0);

    cout << "Listening for incoming connections..." << endl;

    char buffer[1024];
    int clientAddrSize = sizeof(clientAddr);
    if ((client = accept(server, (SOCKADDR *)&clientAddr, &clientAddrSize)) != INVALID_SOCKET)
    {
        cout << "Client connected!" << endl;
        recv(client, buffer, sizeof(buffer), 0);
        cout << "Client says: " << buffer << endl;
        memset(buffer, 0, sizeof(buffer));

        closesocket(client);
        cout << "Client disconnected." << endl;
    }
}

int main()
{
    ServerApp();
}

2 Ответов

Рейтинг:
2

Jochen Arndt

Вы должны определить протокол (или использовать существующий). Например, можно создать структуру, содержащую дополнительную информацию, необходимую получателю для сохранения изображений в виде файлов:

#include <stdint.h>

struct myheader {
    uint32_t id; // an ID to identify the header
    uint32_t hdr_len; // the total length of this header
    uint32_t file_num; // the index for this file
    uint32_t file_count; // the total number of files
    uint32_t file_len; // the length of the file
    uint32_t name_len; // the length of the file name
    wchar_t file_name[1]; // the name of the file without path
};

Теперь отправитель должен создать буфер для этой структуры, в котором есть дополнительное пространство для имени файла, и для каждого файла заполнить элементы, отправить буфер и отправить содержимое файла изображения:
uint8_t buf[sizeof(myheader) + sizeof(wchar_t) * MAX_FILE_NAME_LEN];
myheader *pHeader = reinterpret_cast<myheader*>(buf);
// initialise pHeader
pHeader->id = MY_HEADER_ID;
pHeader->file_num = 0;
pHeader->file_count = 1; // or more
pHeader->name_len = sizeof(wchar_t) * (1 + wcslen(file_name));
wcscpy(pHeader->file_name, file_name);
pHeader->hdr_len = sizeof(myheader) - sizeof(wchar_t) + pHeader->name_len;
pHeader->file_len = file_len;

// send header using pointer buf and size pHeader->hdr_len
// sende image file content
// increment pHeader->file_num and process next file


Приемник должен сделать это аналогично:
uint8_t buf[sizeof(myheader) + sizeof(wchar_t) * MAX_FILE_NAME_LEN];
myheader *pHeader = reinterpret_cast<myheader*>(buf);
// Read into buf with sizeof(myheader)
// Read into pHeader->file_name+1 with pHeader->hdr_len - sizeof(myheader)
// Allocate buffer for image content (full size pHeader->file_len or partial size for writing to file)
// Read image file content into buffer and process data (e.g. write to file)
// Repeat until pHeader->file_num == pHeader->file_count - 1


Member 13123405

В какой части кода я должен внести эти изменения?

Jochen Arndt

При отправке и получении. Это просто пример того, как это может быть реализовано.

Вам все равно придется добавить код для передачи имен файлов изображений и считывания их в память для отправки, а также обработки полученных данных (записи файлов).

Рейтинг:
0

Richard MacCutchan

Вы отправляете файлы изображений так же, как и любые другие данные. Вам просто нужно убедиться, что каждая конечная точка может понять, когда начинается и заканчивается новый файл.