https://github.com/30mb1/cgi_server
Simple CGI server on C using sockets.
https://github.com/30mb1/cgi_server
c cgi cgi-server linux-server network-programming server socket-programming socket-server
Last synced: about 2 months ago
JSON representation
Simple CGI server on C using sockets.
- Host: GitHub
- URL: https://github.com/30mb1/cgi_server
- Owner: 30mb1
- Created: 2017-03-17T19:56:00.000Z (about 8 years ago)
- Default Branch: master
- Last Pushed: 2018-09-04T12:35:30.000Z (over 6 years ago)
- Last Synced: 2025-02-13T06:33:31.235Z (3 months ago)
- Topics: c, cgi, cgi-server, linux-server, network-programming, server, socket-programming, socket-server
- Language: C
- Homepage:
- Size: 42 KB
- Stars: 3
- Watchers: 2
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# web-server с функциональностью CGI #
CGI - это стандарт интерфейса, используемый для связи внешней программы для связи с сервером. Программу, которая работает по такому интерфейсу совместно с веб-сервером, принято называть шлюзом, хотя многие предпочитают названия «скрипт» или «CGI-программа». По сути позволяет использовать консоль ввода и вывода для взаимодействия с клиентом.
Сам интерфейс разработан таким образом, чтобы можно было использовать любой язык программирования, который может работать со стандартными устройствами ввода-вывода. Такими возможностями обладают даже скрипты для встроенных командных интерпретаторов операционных систем, поэтому в простых случаях могут использоваться даже командные скрипты.
CGI является одним из наиболее распространённых средств создания динамических сайтов. Этот стандарт используют такие популярные веб-сервера, как например, [Nginx](https://ru.wikipedia.org/wiki/Nginx) или [Apache](https://ru.wikipedia.org/wiki/Apache_HTTP_Server).
## OVERVIEW ##
Сервер умеет закрепляться на определенному хост:порт и слушать входящие соединения. На заданном адресе выдается HTML-страничка, если запрос корректен, либо страница с ошибкой 404, если запрашиваемой страницы не существует. Также реализован cgi-скрипт показывающий время при нажатии на кнопки на главной странице.
## DOCUMENTATION ##
```
#!htdocs/
cgi-bin/
install.c
utility.c
utility.h
main.c
Makefile
```* *htdocs* содержит всю статику: HTML и CSS файлы сервера.
* В *cgi-bin* хранятся используемые cgi-скрипты - на данный момент только программа, выводящая текущую дату/время.
* *install.c* это установочный скрипт, создающий .service файл для оформления сервера как службы systemd.
* *main.c* - содержит все функции, отвечающие за настройку и запуск сервера.
* *utility.c* - включает некоторые вспомогательные функции, такие как парсинг запроса клиента char * parse_request(...), поиск запрашиваемых файлов и отправка их клиенту void GET(...) и тд.
* *Makefile* - установочный make-file, содержащий все инструкции по компиляции и установке сервера.## INSTALLING AND RUNNING SERVER ##
Устанавливаем с помощью make. Установочный скрипт скомпилирует и переместит исполняемый файл в папку /usr/local/bin, затем создаст .service файл и поместит его в /etc/systemd/system/:
```
cd cgi/
make install
```Сервер теперь можно запускать так же, как и системные службы(работает только на Ubuntu,
т.к помещает юнит-файл в папку /etc/systemd/system/, которая не является установочной на
других системах). По дефолту сервер запустится на 127.0.0.1:1235. Чтобы выставить свои настройки, нужно изменить config файл:```
service cgi start
service cgi stop
```## HOW IT WORKS ##
При запуске программа создает PID файл, в который записывает ID текущего процесса, чтобы в дальнейшем можно было послать на него сигнал для завершения работы. Если во время старта сервера возникла ошибка, файл не создается.
```
#!c//creating PID file
FILE * file = fopen(path_to_pidfile, "a+");
fprintf(file, "%d", getpid());
fclose(file);//killing running server
FILE * file = fopen(path_to_pidfile, "r+");
fscanf(file, "%d", &pid);
kill(pid, SIGTERM);
fclose(file);
remove(path_to_pidfile);
```
Далее с помощью набора функций для работы с сокетами настраиваем наш сервер.
Если все прошло без ошибок, начинаем принимать входящие соединения. Для каждого принятого соединения создаем отдельный процесс, родительский процесс при этом продолжает слушать.```
#!cpid_t pid = fork();
if (0 == pid) { //if it is child process - interact connection
handle_request(client_socket, &client_address, htdocs);
exit(0);
} else { //otherwise close socket and continue listening
close(client_socket);
}
```Дочерний процесс считывает запрос, обрабатывает его и выдает страницу ответ: если файл был найден, то выдается соответствующая страничка, в противном случае пользователь получит страницу с ошибкой 404. Вся статика хранится в папке htdocs сервера.
```
#!cread(client_socket, recv_buffer, sizeof(recv_buffer));
char *query_str = parse_request(recv_buffer);
...
GET(client_socket, query_str, maindir);
```При нажатии на главной странице на кнопку "get current time" выполняется скрипт, возвращающий текущую дату/время:
```
#!cif (strcmp(query_str + strlen(query_str) - 4, "cgi?") == 0) {
...
execve(main_dir, arg, empty2); //execute cgi-script
close(client_socket);
}```
### Отчет по проделанной работе ###
На данный момент реализовано:
1. Веб-сервер выдает статические страницы и обслуживает одновременно несколько подключений.
2. Сервер оформлен в виде службы для systemd.
3. Сервер корректно обрабатывает ошибочные запросы.
4. Сервер умеет работать со сторонними программами и выдавать результат их работы(на стадии разработки).Coming soon:
1. Поддержка POST запросов.