Введение в CGI

Стандартный поток ввода


Cчитывать данные в программу на C принято из файлов. При этом файлы ассоциируются с потоками данных. Поток данных — это последовательность октетов (8 бит, или более привычно — байт). Если считывается текстовый файл, то мы имеем дело с последовательностью символов. Если считываем двоичный файл — имеем дело с октетами (байтами). Все функции С, которые работают с файлами ориентированы на эту модель — на потоки данных.

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

Самый простой способ чтения потока стандартного ввода обеспечивает функция посимвольного чтения getc():

#include <stdio.h> #include <stdlib.h> #include <malloc.h> void main(argc,argv,env) int argc; char *argv[]; char *env[]; { char *query; int length; length = atoi(getenv("CONTENT_LENGTH")); query = (char *) malloc(length+1); memset(query,'\000',length+1); for(int i=0;i<length;i++) { query[i] = getc(); } free(query); }

Функция getc() доставляет по одному символу из потока стандартного ввода. Не следует думать, что это медленный способ чтения. Во-первых, сервер передает данные через канал (pipe), а во-вторых, поток буферизуется. Поэтому даже посимвольное чтение данных происходит достаточно быстро.

Можно прочитать и все данные сразу. Для этого пользуются функцией fread():

#include <stdio.h> #include <stdlib.h> #include <malloc.h> void main(argc,argv,env) int argc; char *argv[]; char *env[]; { char *query; int length; length = atoi(getenv("CONTENT_LENGTH")); query = (char *) malloc(length+1); memset(query,'\000',length+1); fread(query,length,1,STDIN); free(query); }

В данном случае мы читаем из потока стандартного ввода STDIN в буфер query ровно length символов.

Последнее замечание. В наших примерах используется функция malloc(). Эта функция отводит память под данные, которые мы считываем со стандартного ввода. После завершения скрипта нужно обязательно освободить эту память, не уповая на то, что после завершения программы вся память все равно освободится. Здесь учитывается два момента. Во-первых, использование такого способа размещения данных связано с попыткой избежать переполнения при использовании областей памяти фиксированной длины, которое приводит к аварийному завершению программы. Во-вторых, при переходе от CGI-скриптов к FastCGI-скриптам это позволяет избежать "утечки" памяти. В FastCGI скрипт не завершается после ответа клиенту, а остается "висеть" в памяти в ожидании следующего запроса. Если память не освободить, то при новом обращении произойдет резервирование новой области памяти. В конечном итоге свободной памяти может и не оказаться.



Содержание раздела