Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ////////////////MHTTPsrv.cpp///////////////////////////////////////
- // MHTTPsrv.cpp: определяет точку входа для консольного приложения.
- //
- #include "stdafx.h"
- #include "MHTTPsrv.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #endif
- // Единственный объект приложения
- CWinApp theApp;
- using namespace std;
- #include <iostream>
- #include <sstream>
- #include <string>
- #include <fstream>
- #include <io.h>
- // Для корректной работы freeaddrinfo в MinGW
- // Подробнее: http://stackoverflow.com/a/20306451
- #define _WIN32_WINNT 0x501
- #include <WinSock2.h>
- #include <WS2tcpip.h>
- // Необходимо, чтобы линковка происходила с DLL-библиотекой
- // Для работы с сокетам
- #pragma comment(lib, "Ws2_32.lib")
- #include <regex>
- #include "get_req.h"
- using std::cerr;
- bool senddata(SOCKET sock, void *buf, int buflen)
- {
- const char *pbuf = (const char *)buf;
- while (buflen > 0)
- {
- int num = send(sock, pbuf, buflen, 0);
- if (num == SOCKET_ERROR)
- {
- if (WSAGetLastError() == WSAEWOULDBLOCK)
- {
- // optional: use select() to check for timeout to fail the send
- continue;
- }
- return false;
- }
- pbuf += num;
- buflen -= num;
- }
- return true;
- }
- bool sendlong(SOCKET sock, long value)
- {
- value = htonl(value);
- return senddata(sock, &value, sizeof(value));
- }
- bool sendfile(SOCKET sock, FILE *f)
- {
- fseek(f, 0, SEEK_END);
- long filesize = ftell(f);
- rewind(f);
- if (filesize == EOF)
- return false;
- if (!sendlong(sock, filesize))
- return false;
- if (filesize > 0)
- {
- char buffer[1024];
- do
- {
- size_t num = min(filesize, sizeof(buffer));
- num = fread(buffer, 1, num, f);
- if (num < 1)
- return false;
- if (!senddata(sock, buffer, num))
- return false;
- filesize -= num;
- } while (filesize > 0);
- }
- return true;
- }
- int main()
- {
- int nRetCode = 0;
- HMODULE hModule = ::GetModuleHandle(nullptr);
- if (hModule != nullptr)
- {
- // инициализировать MFC, а также печать и сообщения об ошибках про сбое
- if (!AfxWinInit(hModule, nullptr, ::GetCommandLine(), 0))
- {
- // TODO: измените код ошибки соответственно своим потребностям
- wprintf(L"Критическая ошибка: сбой при инициализации MFC\n");
- nRetCode = 1;
- }
- else
- {
- WSADATA wsaData; // служебная структура для хранение информации
- // о реализации Windows Sockets
- // старт использования библиотеки сокетов процессом
- // (подгружается 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_family = AF_INET; // AF_INET определяет, что будет
- // использоваться сеть для работы с сокетом
- hints.ai_socktype = SOCK_STREAM; // Задаем потоковый тип сокета
- hints.ai_protocol = IPPROTO_TCP; // Используем протокол TCP
- hints.ai_flags = AI_PASSIVE; // Сокет будет биндиться на адрес,
- // чтобы принимать входящие соединения
- // Инициализируем структуру, хранящую адрес сокета - addr
- // Наш HTTP-сервер будет висеть на 8000-м порту локалхоста
- result = getaddrinfo("127.0.0.1", "8000", &hints, &addr);
- // Если инициализация структуры адреса завершилась с ошибкой,
- // выведем сообщением об этом и завершим выполнение программы
- if (result != 0) {
- cerr << "getaddrinfo failed: " << result << "\n";
- WSACleanup(); // выгрузка библиотеки Ws2_32.dll
- return 1;
- }
- // Создание сокета
- int listen_socket = socket(addr->ai_family, addr->ai_socktype,
- addr->ai_protocol);
- // Если создание сокета завершилось с ошибкой, выводим сообщение,
- // освобождаем память, выделенную под структуру addr,
- // выгружаем dll-библиотеку и закрываем программу
- if (listen_socket == INVALID_SOCKET) {
- cerr << "Error at socket: " << WSAGetLastError() << "\n";
- freeaddrinfo(addr);
- WSACleanup();
- return 1;
- }
- // Привязываем сокет к IP-адресу
- result = bind(listen_socket, addr->ai_addr, (int)addr->ai_addrlen);
- // Если привязать адрес к сокету не удалось, то выводим сообщение
- // об ошибке, освобождаем память, выделенную под структуру addr.
- // и закрываем открытый сокет.
- // Выгружаем DLL-библиотеку из памяти и закрываем программу.
- if (result == SOCKET_ERROR) {
- cerr << "bind failed with error: " << WSAGetLastError() << "\n";
- freeaddrinfo(addr);
- closesocket(listen_socket);
- WSACleanup();
- return 1;
- }
- // Инициализируем слушающий сокет
- if (listen(listen_socket, SOMAXCONN) == SOCKET_ERROR) {
- cerr << "listen failed with error: " << WSAGetLastError() << "\n";
- closesocket(listen_socket);
- WSACleanup();
- return 1;
- }
- const int max_client_buffer_size = 1024;
- char buf[max_client_buffer_size];
- int client_socket = INVALID_SOCKET;
- for (;;) {
- // Принимаем входящие соединения
- client_socket = accept(listen_socket, NULL, NULL);
- if (client_socket == INVALID_SOCKET) {
- cerr << "accept failed: " << WSAGetLastError() << "\n";
- closesocket(listen_socket);
- WSACleanup();
- return 1;
- }
- result = recv(client_socket, buf, max_client_buffer_size, 0);
- std::stringstream response; // сюда будет записываться ответ клиенту
- std::stringstream response_body; // тело ответа
- if (result == SOCKET_ERROR) {
- // ошибка получения данных
- cerr << "recv failed: " << result << "\n";
- closesocket(client_socket);
- }
- else if (result == 0) {
- // соединение закрыто клиентом
- cerr << "connection closed...\n";
- }
- else if (result > 0) {
- // Мы знаем фактический размер полученных данных, поэтому ставим метку конца строки
- // В буфере запроса.
- buf[result] = '\0';
- // Данные успешно получены
- // формируем тело ответа (HTML
- std::string line;
- line = string(buf);
- get_req req;
- req.get_patch(line);
- line = "." + line;
- cerr << "File "<<line<<"\n";
- if (req.get_exp(line) == "html")
- {
- std::ifstream file;
- file.open(line);
- if (file)
- {
- while (file)
- {
- std::string str;
- std::getline(file, str);
- response_body << str << "\n";
- }
- file.close();
- }
- else
- {
- response_body << "File not found\n";
- cerr << "File " << line << " not found\n";
- }
- // Формируем весь ответ вместе с заголовками
- response << "HTTP/1.1 200 OK\r\n"
- << "Version: HTTP/1.1\r\n"
- << "Content-Type: text/html; charset=utf-8\r\n"
- << "Content-Length: " << response_body.str().length()
- << "\r\n\r\n"
- << response_body.str();
- // Отправляем ответ клиенту с помощью функции send
- result = send(client_socket, response.str().c_str(),
- response.str().length(), 0);
- }
- else
- {
- cerr << "Send binary file " << line << "\n";
- FILE *filehandle = fopen(line.c_str(), "rb");
- if (filehandle != NULL)
- {
- sendfile(client_socket, filehandle);
- fclose(filehandle);
- }
- }
- if (result == SOCKET_ERROR) {
- // произошла ошибка при отправле данных
- cerr << "send failed: " << WSAGetLastError() << "\n";
- }
- // Закрываем соединение к клиентом
- closesocket(client_socket);
- }
- }
- // Убираем за собой
- closesocket(listen_socket);
- freeaddrinfo(addr);
- WSACleanup();
- return 0;
- }
- }
- else
- {
- // TODO: Измените код ошибки соответственно своим потребностям
- wprintf(L"Критическая ошибка: неудачное завершение GetModuleHandle\n");
- nRetCode = 1;
- }
- return nRetCode;
- }
- ///////////////////get_req.cpp///////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "get_req.h"
- #include <vector>
- get_req::get_req()
- {
- }
- std::string get_req::get_patch(std::string &req)
- {
- std::vector<std::string> patch;
- char *tmp = new char[req.length() + 1];
- strcpy(tmp, req.c_str());
- char * pch = strtok(tmp, " "); // во втором параметре указаны разделитель (пробел, запятая, точка, тире)
- while (pch != NULL) // пока есть лексемы
- {
- patch.push_back(pch);
- pch = strtok(NULL, " ");
- }
- req = patch[1];
- return patch[1];
- }
- std::string get_req::get_exp(std::string & req)
- {
- std::vector<std::string> patch;
- char *tmp = new char[req.length() + 1];
- strcpy(tmp, req.c_str());
- char * pch = strtok(tmp, "."); // во втором параметре указаны разделитель (пробел, запятая, точка, тире)
- while (pch != NULL) // пока есть лексемы
- {
- patch.push_back(pch);
- pch = strtok(NULL, ".");
- }
- return patch.back();
- }
- ///////////////////////////get_req.h////////////////////////
- #pragma once
- class get_req
- {
- public:
- get_req();
- std::string get_patch(std::string &req);
- std::string get_exp(std::string &req);
- private:
- std::string input;
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement