проблема с ручкой чтения - PullRequest
1 голос
/ 21 июня 2011

Я работаю над сетевым программированием с использованием epoll, и у меня есть этот код ...

int read = read(socket, buf, bufsize);

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

Один из примеров: если клиент отправил 500 байтов, но каким-то образом попал в два пакета по 250 байтов, то нет способа справиться с этой ситуацией.

Я посмотрел в Интернете и нашел этот код

int handle_read(client *cli, struct epoll_event *ev) {
    size_t len = 4096;
    char *p;
    ssize_t received;

    cli->state = 1;
    if (cli->buffer != NULL) {
        //free(cli->buffer);
        //printf("Buff not null %s\n", cli->buffer);
    }

    //allocate space for data
    cli->buffer = (char*)malloc( (size_t)(sizeof(char) * 4096) );
    p = cli->buffer;

    do { //read until loop conditions
        received = recv(ev->data.fd, p, len, 0);
        if (received < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
            //if error, remove from epoll and close socket
            printf("Handle error!!!\nClient disconnected!\n");
            epoll_ctl(epollfd, EPOLL_CTL_DEL, ev->data.fd, ev);
            close(ev->data.fd);
        }
        p = &cli->buffer[received];
    } while (received >= len && errno != EAGAIN && errno != EWOULDBLOCK);

    return received;
}

Как вы думаете, ребята, он обрабатывает все исключения, которые могут возникнуть при получении?Также не могли бы вы предоставить мне учебные пособия или примеры, которые обрабатывают исключения сокетов?Примеры кодов онлайн не охватывают детали .. Заранее спасибо

Ответы [ 2 ]

1 голос
/ 21 июня 2011

recv может вернуть любую из трех вещей, и ваш код должен правильно обрабатывать каждую из них:

1) Положительное число.Это означает, что он читает несколько байтов.

2) Отрицательное число.Это означает, что произошла «ошибка».

3) Ноль.Это означает, что другой конец соединения успешно выполнил shutdown() (или close()) на сокете.(Как правило, возвращение 0 из read () или recv () означает EOF.)

В случае «ошибки» далее делятся на «EAGAIN или EWOULDBLOCK» и «все остальное».».Первые два означают, что это неблокирующий сокет, и на данный момент не было данных, которые можно было бы вам предоставить.Возможно, вы захотите вернуться назад и снова вызвать poll () (или select () или epoll ()), чтобы избежать ожидания ожидания ...

«Все остальное» означает настоящую ошибку.Вы должны справиться с этим тоже;полный список см. в спецификации POSIX для recv () .

Учитывая все это, я бы сказал, что ваш пример кода плох по нескольким причинам.Он не обрабатывает 0 (закрытое соединение) должным образом.Он не обрабатывает никаких ошибок.Он выполняет цикл занятости, когда recv() возвращает EAGAIN / EWOULDBLOCK.

О, и использует sizeof(char), что является верным признаком того, что он был написан кем-то, кто не знаком сязыки программирования C или C ++.

0 голосов
/ 21 июня 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...