Использование recv () для получения фрагментов сообщения - PullRequest
0 голосов
/ 21 января 2020

Я работаю с WebSockets. Я создал небольшой тестовый клиент, который разбивает сообщение и затем отправляет его по частям. Например, сообщение типа:

PROTOCOL HTTP ACTION UPDATE

может быть отправлено как

PROTOC

как один кусок, а затем

OL HTT

как другой, в отличие от отправки полного сообщения в одном фрагменте как PROTOCOL HTTP ACTION UPDATE, что также возможно.

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

Это то, что я пытаюсь, но я не уверен, что это правильный путь. Должен ли я всегда сохранять размер буфера равным 200 при получении? Когда я должен выйти из l oop?

void recv_all(){
            char rec_buffer[200]
            while(1) {
              ssize_t bytes_rec = recv(socket_fd, rec_buffer, sizeof(rec_buffer),0);

            }
}

Ответы [ 2 ]

1 голос
/ 23 января 2020
Сокеты

(stream) работают с байтовыми потоками, а не с сообщениями. Таким образом, они обеспечивают способ получения потока байтов между конечными точками и ничего более. Если вам нужны какие-то «сообщения», вам нужно обработать поток байтов, чтобы найти источники сообщений и разбить их на сообщения самостоятельно.

Обычный способ сделать это с помощью буфера, такого как C Объект FILE или потоковый поток C ++. Вы организуете чтение байтов из сокета в буфер, а затем проверяете, есть ли в буфере полное сообщение, обычно путем поиска маркера окончания / границы сообщения (такого как \ r \ n или просто \ n). Если есть, вы удаляете (просто) сообщение из буфера.

Это довольно легко сделать в C с POSIX - вы можете использовать fdopen, чтобы открыть ФАЙЛ с дескриптором сокета, а затем используйте fgets или getline, чтобы прочитать сообщение до новой строки.

0 голосов
/ 22 января 2020

вы можете использовать возвращаемое значение из вызовов на read(), а затем использовать strcat(), чтобы склеить части сообщения обратно.

В соответствии с OP, сообщение заканчивается на \r\n здесь пример того, как прочитать сообщение как несколько пакетов.

char *message = malloc( MAX_MSG_LEN +1 );
if( ! message )
{
    perror( "malloc failed" );
    exit( EXIT_FAILURE );
}

// implied else, malloc successful

recv_buf[0] = '\0';
size_t msgLen = 0;
int done = 0;

while( msgLen < MAX_MSG_LEN && !done)
{
    ssize_t byteCount = read( socket_fd, message, MAX_MSG_LEN );

    if( ! byteCount )
    {
        // handle error of sender closing the socket
    }

    else if( byteCount < 0 )
    {
        // handle I/O error
    }

    else
    {
        if( msgLen+byteCount > sizeof( recv_buf ) )
        {
            // handle error of message too long
        }

        else
        {
            message[ byteCount ] = '\0';
            strcat( recv_buf, message );
            msgLen += byteCount;
            if( memcmp( recv_buf[msgLen-2], "\r\n", 2 ) == 0 )
            {
                 done = 1;
            }
        }
    }
}
free( message );

Примечание. Я не запускал приведенный выше пример, поэтому возможна некоторая отладка.

...