Форум программистов, компьютерный форум, киберфорум
C++: Сети
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.50/4: Рейтинг темы: голосов - 4, средняя оценка - 4.50
1 / 1 / 0
Регистрация: 06.11.2014
Сообщений: 18
1

Web Сервер

09.11.2015, 21:05. Показов 734. Ответов 3
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый вечер!

Есть программка которая реализует простой web-сервер для обработки GET-запросов.
Программа хорошо работает во всех браузерах помимо IE.
Подскажите в чем проблема и есть ли какие-либо ошибки в коде?

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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#include <iostream>
#include <WinSock2.h>
#include <WS2tcpip.h> //заголовочный файл для работы с IP-адресам
#include <sstream>
#include <string>
 
#pragma comment(lib, "Ws2_32.lib")
using namespace std;
 
char html[] =
"HTTP/1.0 200 OK\r\n"
"Connection: close\r\n"
"Content - Type: text / plain; charset = utf - 8\r\n"
"Content - Language: ru\r\n"
"Content - Length: 5\r\n"
"\r\n";
long lSize;
char *buffer;
 
void sendRespond(SOCKET client_socket)
{
    char *tmp = new char[lSize + strlen(html)];
 
    int intlt = 0;
    for (; intlt < strlen(html); intlt++)
        tmp[intlt] = html[intlt];
    for (int i = 0; intlt < strlen(html) + lSize; intlt++, i++)
        tmp[intlt] = buffer[i];
 
    send(client_socket, tmp, intlt, 0);
}
 
bool loadFile(char * file)
{
    
    if (file[2] == 0)
    file = ".\\index.html";
    FILE *File = fopen(file, "rb");
    if (File == NULL)
        return false;
 
    fseek(File, 0, SEEK_END);
    lSize = ftell(File);
    rewind(File);
 
    buffer = new char[lSize];
    fread(buffer, sizeof(char), lSize, File);
    fclose(File);
    return true;
}
 
 
int handleClient(SOCKET client_socket)
{
    char cCur = 0, cLast = 0, cBuf = 0;
    bool headersEnded = false;
    char reqHdr[1024] = { 0 };
    int reqHdrLen = 0;
 
    // Ожидание, пока мы не получили конец заголовков HTTP запроса
    // Прежде чем начать отправку ответа
    do {
        int count = recv(client_socket, &cBuf, 1, 0);
        if (count == SOCKET_ERROR) {
            cout << "Could not recv from client";
            return 1;
        }
 
        if (cBuf != '\r' && cBuf != '\b') {
            cLast = cCur;
            cCur = cBuf;
            if (reqHdrLen < 1024)
                reqHdr[reqHdrLen++] = cBuf;
        }
 
        if (cCur == '\n' && cLast == '\n')
            headersEnded = true;
    } while (!headersEnded); 
    int verbose = 1;
    if (verbose)
    cout << reqHdr; //Выводим запросы
 
    char get[1024] = {0};
    int cursor = 0, target = 0;
    while (reqHdr[cursor++] != ' '){}
    get[target++] = '.';
    get[target++] = '\\';
    cursor++;
    
    while (reqHdr[cursor] != ' ')
        get[target++] = reqHdr[cursor++];
 
    if (strstr(get, ".\\error"))
    {
        char* ptr = "HTTP/1.1 503 Service Temporarily Unavailable\r\nConnection: close\r\n\r\nSERVER PUT DOWN";
        send(client_socket, ptr, strlen(ptr), 0);
 
        return 0;
    }
 
    ;
    if (loadFile(get))
        sendRespond(client_socket);
    else
    {
        char* ptr = "HTTP/1.1 404 File Not Found\r\nConnection: close\r\n\r\nNETU STRANICY";
        send(client_socket, ptr, strlen(ptr), 0);
    }
    return 0;
}
 
 
int main(int argc, char argv[])
{
    
//  char test_page[6592];
    // служебная структура для хранение информации
    // о реализации Windows Sockets
    WSADATA wsaData;  
 
    // старт использования библиотеки сокетов процессом
    // (подгружается Ws2_32.dll)
    int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
 
    // Если произошла ошибка подгрузки библиотеки
    if (result != 0) {
        cerr << "WSAStartup failed: " << result << "\n";
        return result;
    }
    
    // Шаблон для инициализации структуры адреса
    struct addrinfo* addr = NULL; // структура, хранящая информацию об IP-адресе  слущающего сокета
    struct addrinfo hints;
    ZeroMemory(&hints, sizeof(hints)); // убедимся, что структура пуста
    hints.ai_flags = AI_PASSIVE; //установка на прием входящих сообщений
    hints.ai_family = AF_UNSPEC;//неважно какой Ipv
    hints.ai_socktype = SOCK_STREAM;//задаем потоковый тип сокета
    hints.ai_protocol = IPPROTO_TCP;//используем протокол TCP
 
    //Инициализируем структуру, храняшую адррес соката - addr
    //HTTP сервер весит на порту, взятый из файла настройки(port.txt);
    result = getaddrinfo("127.0.0.1", "80", &hints, &addr);
    //Если инициализация не удалась, выводим сообщение
    // и завершаем программу
    if (result != 0) {
        cerr << "getaddrinfo failed: " << result << "\n";
        WSACleanup();
        return 1;
    }
    //Создание сокета
    int s = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
    //Если создание не удалалось, выводим сообщение, освобождаем память
    //выгружаем dll-библиотеку, закрываем программу
    if (s == INVALID_SOCKET)
    {
        cerr << "Error at socket: " << WSAGetLastError() << "\n";
        freeaddrinfo(addr);
        WSACleanup();
        return 1;
    }
 
    //Привязка сокета к адресу
    result = bind(s, addr->ai_addr, (int)addr->ai_addrlen);
 
    //Если привязка не удалась, выводим сообщение
    //освобождаем память, закрываем сокет
    //выгружаем dll-библиотеку и закрываем программу
 
    if (result == SOCKET_ERROR){
        cerr << "Bind failed with error: " << WSAGetLastError << "\n";
        freeaddrinfo(addr);
        closesocket(s);
        WSACleanup();
        return 1;
    }
 
    // Инициализируем слушающий сокет
    //Если инициализация не удалась, выводим сообщение,
    //закрываем сокет, выгружаем dll-библиотеку
    //закрываем программу
    if (listen(s, 5) == SOCKET_ERROR) {
        cerr << "Listen failed with error: " << WSAGetLastError() << "\n";
        closesocket(s);
        WSACleanup();
        return 1;
    }
    //cout << "Listening on port: " << port;
    //Принимаем входящие сообщения
    //Если произошла ошибка соединения, выводим сообщение,
    //закрываем сокет, выгружаем dll-библиотеку
    //закрываем программу
    int client_socket = INVALID_SOCKET;
    while (client_socket = accept(s, NULL, NULL))
    {
        if (client_socket == INVALID_SOCKET){
            cerr << "Accept failed: " << WSAGetLastError() << "\n";
            closesocket(s);
            WSACleanup();
            return 1;
        }
        if (client_socket == SOCKET_ERROR) {
            //ошбика получения данных
            cerr << "Recv failed: " << result << "\n";
            closesocket(client_socket);
        }
        else if (client_socket == 0) {
            cerr << "\nConnection closed...\n";
        }
        else if (client_socket > 0) {
            handleClient(client_socket);
            if (client_socket == SOCKET_ERROR) {
                // произошла ошибка при отправле данных
                cerr << "send failed: " << WSAGetLastError() << "\n";
            }
        }
        // Закрываем соединение к клиентом
        closesocket(client_socket);
    }
        closesocket(s);
        freeaddrinfo(addr);
        WSACleanup();
        return 0;
}
Добавлено через 34 минуты
Проблему решил, виноват был сама страница сайта.
Но если кому-то не трудно, подскажите насчет ошибок в коде или возможно что-то надо добавить или убрать.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
09.11.2015, 21:05
Ответы с готовыми решениями:

Свой web сервер
От переизбытка свободного времени решил &quot;написать сайт на c++&quot; Но опыта в этой области совсем...

Web Страница открывается частично, web сервер выдает лишь часть информации
Всем доброе время суток! Никак не могу решить у себя проблему, обыскал весь интернет по гуглу,...

Технология создания приложений на основе многоуревневой архитектуры клиент - Web-сервер - сервер баз данных
Технология создания приложений на основе многоуревневой архитектуры клиент Web-сервер – сервер...

если на одном компе стоит сервер Оракла, на втором компе - Web сервер(IIS), то..
Всем привет! хотелось бы уточнить, если на одном компе стоит сервер Оракла, на втором компе - Web...

3
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
09.11.2015, 23:22 2
C++
1
2
3
4
5
6
7
8
// Ожидание, пока мы не получили конец заголовков HTTP запроса
    // Прежде чем начать отправку ответа
    do {
        int count = recv(client_socket, &cBuf, 1, 0);
        if (count == SOCKET_ERROR) {
            cout << "Could not recv from client";
            return 1;
        }
Не будет это работать. HTTP-клиент вовсе не обязан сразу закрывать соединение,
он может послать второй запрос, третий... Может вообще послать сразу штук 5
запросов (это называется request pipelining). Так что без кода парсинга
HTTP-потока здесь не обойтись.

Ну и в одном потоке это все тоже делать не советую: пока обслуживаем одного
клиента, всем остальным сервер недоступен. Масштабируемости никакой.
0
Эксперт С++
3071 / 1409 / 425
Регистрация: 19.01.2009
Сообщений: 3,880
10.11.2015, 11:00 3
Dragon001, плюс, к тому что уже указали:
1) каждый вызов loadFile() - утечка памяти адресуемой через указатель buffer (delete[] buffer перед выделением новой памяти, либо лучше всего проверка сколько байт уже было выделено и если в буффере меньше байт чем нам нужно то тогда сначал удаляем предыдущую выделенную память и затем выделяем сколько нам нужно);
2) каждый вызов sendRespond() - утечка памяти адресуемой через указатель tmp (тоже что в 1);
3) HTTP заголовки "Content - Type", "Content - Length" и т.д. пишутся без пробелов;
4) в заголовке Content-Length нужно указывать кол-во байт в теле отклика;
5) выделение памяти tmp в sendRespond() имхо избыточно, т.к. все что мы хотим отослать находиться уже в памяти и можно избавиться от копирования за счет нескольких посылок данных в сокет (Йон Снейдер Эффективное программирование TCP/IP, совет 26);
6) задайтесь вопросом сколько байт памяти динамически запросит ваш сервер если клиент захочет скачать файл, допустим в 500 MB. Как лучше обработать данную ситуацию без выделения такого большого кол-ва памяти?
1
1 / 1 / 0
Регистрация: 06.11.2014
Сообщений: 18
11.11.2015, 20:36  [ТС] 4
Убежденный, schdub, благодарю, буду исправлять
0
11.11.2015, 20:36
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
11.11.2015, 20:36
Помогаю со студенческими работами здесь

Web сервер
Есть проблема, не могу понять из-за чего!!! Сервис http запускается нормально, все ок. Но при...

Web-сервер.
Всем привет , пришел я на этот форум с проблемой.Начал заниматься web разработками.Хочу ...

WEB Сервер
Привет. Извините, если не в тему. Пытаюсь поднять WEB-сервер, в связке wi-fi модуль spb800 и...

Web сервер
помогите запустить web сервер пожалуйста. и желательно еще подскажите, как запустить консоль?


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

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru