Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.81/43: Рейтинг темы: голосов - 43, средняя оценка - 4.81
 Аватар для danek130995
33 / 33 / 3
Регистрация: 25.05.2014
Сообщений: 1,137

Свой мини веб-сервер

07.04.2016, 21:12. Показов 7904. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
У меня задание по предмету написать простейший веб-сервер, работающий по протоколу http. Я прочел гайд Биджа, состряпал код, который запускает сервер и ждет подключений, и когда получает, отправляет Hello, World. Вот код:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
** server.c -- a stream socket server demo
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
 
#define PORT "3491"  // the port users will be connecting to
 
#define BACKLOG 10   // how many pending connections queue will hold
 
void sigchld_handler(int s)
{
    // waitpid() might overwrite errno, so we save and restore it:
    int saved_errno = errno;
 
    while(waitpid(-1, NULL, WNOHANG) > 0);
 
    errno = saved_errno;
}
 
 
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
    if (sa->sa_family == AF_INET) {
        return &(((struct sockaddr_in*)sa)->sin_addr);
    }
 
    return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
 
int main(void)
{
    int sockfd, new_fd;  // listen on sock_fd, new connection on new_fd
    struct addrinfo hints, *servinfo, *p;
    struct sockaddr_storage their_addr; // connector's address information
    socklen_t sin_size;
    struct sigaction sa;
    int yes=1;
    char s[INET6_ADDRSTRLEN];
    int rv;
    char* response;
    response = "Hello world";
 
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE; // use my IP
 
    if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        return 1;
    }
 
    // loop through all the results and bind to the first we can
    for(p = servinfo; p != NULL; p = p->ai_next) {
        if ((sockfd = socket(p->ai_family, p->ai_socktype,
                p->ai_protocol)) == -1) {
            perror("server: socket");
            continue;
        }
 
        if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
                sizeof(int)) == -1) {
            perror("setsockopt");
            exit(1);
        }
 
        if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
            close(sockfd);
            perror("server: bind");
            continue;
        }
 
        break;
    }
 
    freeaddrinfo(servinfo); // all done with this structure
 
    if (p == NULL)  {
        fprintf(stderr, "server: failed to bind\n");
        exit(1);
    }
 
    if (listen(sockfd, BACKLOG) == -1) {
        perror("listen");
        exit(1);
    }
 
    sa.sa_handler = sigchld_handler; // reap all dead processes
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;
    if (sigaction(SIGCHLD, &sa, NULL) == -1) {
        perror("sigaction");
        exit(1);
    }
 
    printf("server: waiting for connections...\n");
 
    while(1) {  // main accept() loop
        sin_size = sizeof their_addr;
        new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
        if (new_fd == -1) {
            perror("accept");
            continue;
        }
 
        inet_ntop(their_addr.ss_family,
            get_in_addr((struct sockaddr *)&their_addr),
            s, sizeof s);
        printf("server: got connection from %s\n", s);
 
        if (!fork()) { // this is the child process
            close(sockfd); // child doesn't need the listener
            if (send(new_fd, response, 11, 0) == -1)
                perror("send");
            close(new_fd);
            exit(0);
        }
        close(new_fd);  // parent doesn't need this
    }
 
    return 0;
}
Сообщение Hello World появляется в браузере. все хорошо. Потом я захотел эмулировать ответ от сервера, т.е. чтобы возвращалось все как должно быть и чтобы бразуер понял что надо интерпретировать html - документ. Поэтому я переписал переменную response:
C
1
response = "HTTP/1.1 200 OK\nServer: nginx\nDate: Thu, 07 Apr 2016 16:54:55 GMT\nContent-Type: text/html\nConnection: close\nX-Powered-By: PHP/5.5.9-1ubuntu4.4\n<!DOCTYPE html>\n<HTML>Hello</HTML>";
Размер в send соответственно указал равным кол-ву символов в этой строке. Но бразуер выдает ошибку при попытке подключения, а если посмотреть ответ от сервера в консоли браузера, то там по нулям заголовки и тд. Почему так происходит?
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
07.04.2016, 21:12
Ответы с готовыми решениями:

AVR мини веб сервер
Доброго времени суток! Товарищи помогите пожалуйста совладать с программным обеспечением данного проекта Lifelovera...

Друзья я хочу сделать свой веб сервер и хочу узнать можно обойтись без ОС Centos
Apache MysQl PHP+CMS все настроено теперь осталось вывести его в инет Что нужно делать? Настроить роутер?

Мини веб браузер
Всем привет. Подскажите пожалуйста есть ли в java готовый компонент для отображения веб страниц или может быть есть уже готовые библиотеки?...

4
Почетный модератор
 Аватар для Humanoid
11559 / 4353 / 453
Регистрация: 12.06.2008
Сообщений: 12,455
07.04.2016, 22:01
Лучший ответ Сообщение было отмечено danek130995 как решение

Решение

Заголовок от данных должен отделяться двумя переводами строки. И для перевода строки по стандарту надо использовать \r\n.
X-Powered-By: PHP/5.5.9-1ubuntu4.4\n<!DOCTYPE html>
замените на
Code
1
X-Powered-By: PHP/5.5.9-1ubuntu4.4\n\n<!DOCTYPE html>
и все \n замените на \r\n... и должно работать.
1
 Аватар для danek130995
33 / 33 / 3
Регистрация: 25.05.2014
Сообщений: 1,137
07.04.2016, 22:21  [ТС]
Humanoid, спасибо большое, заработало. Дело было в этих двух пробелах. Кстати, без \r тоже работает. А еще вопрос:почему иногда, через раз, проскакивает в браузере ошибка все равно:Соединение было сброшено. Через раз-другой. Почему так?
0
Почетный модератор
 Аватар для Humanoid
11559 / 4353 / 453
Регистрация: 12.06.2008
Сообщений: 12,455
07.04.2016, 22:27
Цитата Сообщение от danek130995 Посмотреть сообщение
Кстати, без \r тоже работает.
Работает на всех браузерах, какие я пробовал... но по стандарту нужны виндовые переводы строки (только в заголовках... сами данные могут быть с любыми переводами строк).

Цитата Сообщение от danek130995 Посмотреть сообщение
почему иногда, через раз, проскакивает в браузере ошибка все равно:Соединение было сброшено. Через раз-другой. Почему так?
Я плохо знаком с форками... подозреваю, что у них общие сокеты и если основной процесс закрывает new_fd, то подключение закрывается... и всё зависит от того, что раньше произойдёт: выполнится send() или close() (просто версия... точно не знаю). Но выглядит очень странно... как минимум напрашивается else перед close(new_fd) ... но как я сказал, я с форками плохо знаком, поэтому не могу сейчас точно ответить.
1
153 / 148 / 66
Регистрация: 20.02.2014
Сообщений: 556
08.04.2016, 11:44
man fork
* The child inherits copies of the parent's set of open file descriptors. Each file descriptor in the child refers to the same open file description (see open(2)) as the corresponding file descriptor in the parent. This
means that the two descriptors share open file status flags, current file offset, and signal-driven I/O attributes (see the description of F_SETOWN and F_SETSIG in fcntl(2)).
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
08.04.2016, 11:44
Помогаю со студенческими работами здесь

Мини сервер до $100
Здравствуйте, Хочу приобрести какой-нибудь mini PC и админить его по SSH. Что-то типа Raspberry Pi, но немного мощней и дороже....

Подбираю веб сервер для веб ресурса
Здравствуйтеhttp://www.onno.ru/ru/witem/34472/- Смотрю на это http://www.onno.ru/ru/witem/50186/ - ибп это стойка выбираю, ...

Дешевый мини сервер на основе Pogoplug
Сейчас все работает на стареньком компьютере 1Ghz + 512Ram. Там бежит 5 сайтов, общая посещаемость около 1000 человек в сутки. Сервер...

Мини-сервер для 2-3 рабочих столов
Привет всем, прошу помочь с выбором комплектующих: Необходимо собрать наиболее компактный мини-сервер для домашнего пользования. На нем...

Мини-сервер под Win/Mac
Всем привет. Решил сменить NSA на что-то более отвечающее моим интересам. Ранее увлекался этой темой, мог сам насоветовать с гору...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
Функция установки текстового статуса в реквизите формы документа
Maks 01.04.2026
Алгоритм из решения ниже реализован на нетиповом документе "ВыдачаОборудованияНаСпецтехнику" разработанного в конфигурации КА2, в дополнении к предыдущему решению. На форме документа создается. . .
К слову об оптимизации
kumehtar 01.04.2026
Вспоминаю начало 2000-х, университет, когда я писал на Delphi. Тогда среди программистов на форумах активно обсуждали аккуратную работу с памятью: нужно было следить за переменными, вовремя. . .
Идея фильтра интернета (сервер = слой+фильтр).
Hrethgir 31.03.2026
Суть идеи заключается в том, чтобы запустить свой сервер, о чём я если честно мечтал давно и давно приобрёл книгу как это сделать. Но не было причин его запускать. Очумелые учёные напечатали на. . .
Модель здравосоХранения 6. ESG-повестка и устойчивое развитие; углублённый анализ кадрового бренда
anaschu 31.03.2026
В прикрепленном документе раздумья о том, как можно поменять модель в будущем
10 пpимет, которые всегда сбываются
Maks 31.03.2026
1. Чтобы, наконец, пришла маршрутка, надо закурить. Если сигарета последняя, маршрутка придет еще до второй затяжки даже вопреки расписанию. 2. Нaдоели зима и снег? Не надо переезжать. Достаточно. . .
Перемещение выделенных строк ТЧ из одного документа в другой
Maks 31.03.2026
Реализация из решения ниже выполнена на примере нетипового документа "ВыдачаОборудованияНаСпецтехнику" с единственной табличной частью "ОборудованиеИКомплектующие" разработанного в конфигурации КА2. . . .
Functional First Web Framework Suave
DevAlt 30.03.2026
Sauve. IO Апнулись до NET10. Из зависимостей один пакет, работает одинаково хорошо как в режиме проекта так и в интерактивном режиме. из сложностей - чисто функциональный подход. Решил. . .
Автоматическое создание документа при проведении другого документа
Maks 29.03.2026
Реализация из решения ниже выполнена на нетиповых документах, разработанных в конфигурации КА2. Есть нетиповой документ "ЗаявкаНаРемонтСпецтехники" и нетиповой документ "ПланированиеСпецтехники". В. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru