Отправить большую строку в сокет - PullRequest
7 голосов
/ 06 июня 2019

Я новичок в C ++ и пришел к этой проблеме.Я пытаюсь отправить большую строку в сокет.Я видел подобные вопросы в стеке, но не смог найти реальный ответ.Например:

Отправка длинной строки через сокет C ++

Отправка строки с сокетами в C ++ (Winsock TCP / IP)

C ++ отправка строки через сокет

Большинство из них полагаются на факт, что send будет отправлять все данные за один вызов, или они будут использовать char * вместоstd::string.

Вот небольшой код, написанный на C:

int SendAll(SOCKET client_socket, const void *data, int data_size)
{
    const char *data_ptr = (const char*) data;
    int bytes_sent;

    while (data_size > 0)
    {
        bytes_sent = send(client_socket, data__ptr, data_size, 0);
        if (bytes_sent == SOCKET_ERROR)
            return -1;

        data_ptr += bytes_sent;
        data_size -= bytes_sent;
    }

    return 1;
}

, и теперь представьте, что вместо const void *data у нас есть std::string data.Вопрос в том, как я могу переместить указатель на данные типа data_ptr += bytes_sent; с std::string?

Один из способов, который я получил, - это получить указатель строки std::stirng, сохранить его в некотором const char * var и затем использовать эту переменную таким же образом (var += bytes_sent).Но так как я новичок в C ++, я не знаю, так ли это на C ++?Это лучшее решение этой проблемы или есть лучшее?спасибо

Ответы [ 2 ]

5 голосов
/ 06 июня 2019

Да, это лучший способ.

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

Что-то вроде:

int SendAll(SOCKET client_socket, const std::string& str)
{
    const char* data_ptr  = str.data();
    std::size_t data_size = str.size();

    int bytes_sent;

    while (data_size > 0)
    {
        bytes_sent = send(client_socket, data_ptr, data_size, 0);
        if (bytes_sent == SOCKET_ERROR)
            return -1;

        data_ptr += bytes_sent;
        data_size -= bytes_sent;
    }

    return 1;
}

Это прекрасно и идиоматично.

Если вы хотите сохранить обе версии функции, просто перенаправьте буфер строки в существующую перегрузку:

int SendAll(SOCKET client_socket, const std::string& str)
{
    return SendAll(
        client_socket,
        reinterpret_cast<const void*>(str.data()),
        str.size()
    );
}
3 голосов
/ 06 июня 2019
ssize_t send(int sockfd, const void *buf, size_t len, int flags);

Это подпись send.Требуется указатель на буфер.Хотя API C ++, вероятно, предпочел бы пару итераторов , а не указатель и размер, на самом деле это невозможно, поскольку требуется указатель на фактический буфер.Так что с этим ничего не поделаешь, правда.Вы можете просто использовать строковую функцию-член data(), чтобы получить указатель на начало буфера и работать с ним.Это должно быть совершенно нормально.

Как подсказывают некоторые программисты чувак в комментариях , вы можете добавить простую перегрузку, которая облегчает это:

int SendAll(SOCKET client_socket, std::string const& str) {
    return SendAll(client_socket, reinterpret_cast<const void*>(str.data()), str.size());
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...