Recv () по одной строке за раз - PullRequest
0 голосов
/ 01 декабря 2011

Я недавно учусь программировать основной веб-сервер на c. Мой сервер, в зависимости от определенных входных данных, будет отправлять различные строки текста, которые заканчиваются пустой строкой, и мне нужно каким-то образом получать их со стороны клиента, чтобы отображать по одной строке за раз.

Прямо сейчас сервер делает что-то вроде

send(socket, sometext, strlen(sometext), 0)
send ...
send(socket, "\n", 2, 0);

....

Клиент:

В настоящее время я использую fdopen для переноса дескриптора файла сокета и чтения с помощью fgets:

FILE *response = fdopen(someSocket, "r");
while(1){
            fgets(input, 500, response);

        if(strcmp(input, "\n") != 0){
            //do some stuff
        }
        else {
            // break out of the loop
            break;
        }
}

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

fclose(response);

Это, однако, корень моих проблем, потому что он не только закрывает файл, но и закрывает сокет, которого у меня не может быть. Кто-нибудь может дать мне какое-нибудь руководство по простым методам, чтобы обойти это? Я думал о том, чтобы, возможно, использовать recv (), но разве это не должно воспринимать все сообщение сразу? Есть ли способ воссоздать поведение fgets, используя recv?

Я действительно новичок во всем этом, спасибо за помощь!

Ответы [ 4 ]

2 голосов
/ 01 декабря 2011

Другая проблема, с которой вы столкнулись, состоит в том, что FILE может прочитать больше данных (после пустой строки) из вашего сокета и буферизовать их, которые будут потеряны, если вы закроете FILE.Решение обеих проблем - НЕ закрывать FILE - просто создайте один FILE с fdopen при первом создании сокета (сразу после вызова connect или accept) и используйте его длявсе данные считываются из сокета.

Еще одно примечание: send(socket, "\n", 2, 0); отправит новую строку и nul - вы, вероятно, захотите send(socket, "\n", 1, 0); или send(socket, "\n\n", 2, 0); в зависимости от того, что делают другие отправители.

1 голос
/ 01 декабря 2011

Ваша единственная реальная альтернатива - написать функцию, которая:

1) вызывает recv () с фиксированным буфером и циклом,

2) возвращает только когда вы получите полную строку(или конец соединения)

3) сохраняет любые "оставшиеся символы для следующего чтения следующей строки текста

IIRC, у Стивенса есть такая функция:

PS: Любая уважающая себя библиотека веб-программирования более высокого уровня даствам функция "getNextLine ()" в основном бесплатно.

1 голос
/ 01 декабря 2011

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

http://en.wikipedia.org/wiki/List_of_HTTP_header_fields

0 голосов
/ 01 декабря 2011

POSIX имеет функцию getline(3), которая может оказаться полезной здесь. Он живет в stdio.h, а прототип -

ssize_t getline(char ** restrict linep, size_t * restrict linecapp, FILE * restrict stream);

Он даже изменит размер буфера (через realloc(3)), чтобы он стал достаточно большим, чтобы вместить строку.

Также есть fgetln(3), который похож и также доступен в широкоформатной версии. Это не стандартно, однако.

...