Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

lab4_HTTPGET / httpserver

.cpp
Скачиваний:
12
Добавлен:
01.02.2019
Размер:
5.55 Кб
Скачать
#include <iostream>
#include <string>
#include <fstream>
#include <vector>

#define _WIN32_WINNT 	0x501

#include <WinSock2.h>
#include <WS2tcpip.h>

#pragma comment(lib, "Ws2_32.lib")


#define IP_ADDRESS		"127.0.0.1"
#define PORT			"80"
#define BUFFER_SIZE		1024

int main()
{
	WSADATA wsaData; 
	int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (result != 0) {
		std::cout << "WSAStartup failed: " << result << std::endl;
		return result;
	}
	struct addrinfo* addr = NULL;
	struct addrinfo hints;
	ZeroMemory(&hints, sizeof(hints));
	hints.ai_family = AF_INET; 
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;
	hints.ai_flags = AI_PASSIVE;
	result = getaddrinfo(IP_ADDRESS, PORT, &hints, &addr);
	if (result != 0) {
		std::cout << "getaddrinfo failed: " << result << std::endl;
		WSACleanup();
		return 1;
	}
	int listen_socket = socket(addr->ai_family, addr->ai_socktype,
		addr->ai_protocol);
	if (listen_socket == INVALID_SOCKET) {
		std::cout << "Error at socket: " << WSAGetLastError() << std::endl;
		freeaddrinfo(addr);
		WSACleanup();
		return 1;
	}
	result = bind(listen_socket, addr->ai_addr, (int)addr->ai_addrlen);
	if (result == SOCKET_ERROR) {
		std::cout << "bind failed with error: " << WSAGetLastError() << std::endl;
		freeaddrinfo(addr);
		closesocket(listen_socket);
		WSACleanup();
		return 1;
	}
	if (listen(listen_socket, SOMAXCONN) == SOCKET_ERROR) {
		std::cout << "listen failed with error: " << WSAGetLastError() << std::endl;
		closesocket(listen_socket);
		WSACleanup();
		return 1;
	}
	char buffer[BUFFER_SIZE];
	int clientSocket = INVALID_SOCKET;
	for (;;) {
		clientSocket = accept(listen_socket, NULL, NULL);
		if (clientSocket == INVALID_SOCKET) {
			std::cout << "accept failed: " << WSAGetLastError() << std::endl;
			closesocket(listen_socket);
			WSACleanup();
			return 1;
		}
		result = recv(clientSocket, buffer, BUFFER_SIZE, 0);
		std::cout << "Recv bytes: " << result << std::endl;
		buffer[result] = '\0';
		std::cout << buffer << std::endl;
		if (result == SOCKET_ERROR) {
			std::cout << "recv failed: " << result << std::endl;
			closesocket(clientSocket);
		}
		else if (result == 0) {
			std::cout << "connection closed" << std::endl;
		}
		else if (result > 0) {
			std::string response;
			std::string htmlFile;
			std::string imageFile;
			std::string recvBuffer;
			std::string fileName;
			size_t beginFileName;
			size_t endFileName;
			size_t lengthFileName;
			recvBuffer.append(buffer);
			if (recvBuffer.find("GET /") != std::string::npos) {
				beginFileName = recvBuffer.find("/") + 1;
				endFileName = recvBuffer.find(" ", beginFileName);
				lengthFileName = endFileName - beginFileName;
				fileName = recvBuffer.substr(beginFileName, lengthFileName);
				if (fileName.empty()) {
					fileName = "index.html";
				}
				std::ifstream f;
				if (fileName.find(".ico") != std::string::npos ||
					fileName.find(".jpg") != std::string::npos ||
					fileName.find(".png") != std::string::npos) {
					f.open(fileName.c_str(), std::ios::binary | std::ios::in);
					if (f.is_open()) {
						std::cout << "Open file " << fileName << std::endl;
						int length;
						f.seekg(0, std::ios::end);
						length = f.tellg();
						f.seekg(0, std::ios::beg);
						char ch;
						while (true) {
							ch = f.get();
							if (f.eof()) break;
							imageFile.push_back(ch);
						}
						f.close();
						response = "HTTP/1.1 200 OK\r\n\
							Content-Length: " + std::to_string(imageFile.length()) +
							"\r\n\r\n" + imageFile;
					}
					else {
						response = "HTTP/1.1 404 Not Found\r\n\
							Version: HTTP/1.1\r\n\
							Content-Type: text/html; charset=utf-8";
					}
				}
				else if (fileName.find(".html") != std::string::npos) {
					f.open(fileName.c_str(), std::ios::in);
					if (f.is_open()) {
						int length;
						f.seekg(0, std::ios::end);
						length = f.tellg();
						f.seekg(0, std::ios::beg);
						char ch;
						while (true) {
							ch = f.get();
							if (f.eof()) break;
							htmlFile.push_back(ch);
						}
						f.close();
						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: " + std::to_string(htmlFile.length()) +
							"\r\n\r\n" + htmlFile.c_str();
					}
				}
				else {
					htmlFile = "<title>404. Страница не найдена</title>\n\
						<center><h2>404</h2>\
						<p>Страница не найдена.</p></center>";
					response = "HTTP/1.1 404 Not Found\r\n\
						Version: HTTP/1.1\r\n\
						Content-Type: text/html; charset=utf-8\r\n\
						Content-Length: " + std::to_string(htmlFile.length()) +
						"\r\n\r\n" + htmlFile.c_str();
				}
			}
			else {
				htmlFile = "<title>400 Bad Request</title>\n\
							<center><h2>400</h2>\
							<p>Bad Request.</p></center>";
				response = "HTTP/1.1 400 Bad Request\r\n\
							Version: HTTP/1.1\r\n\
							Content-Type: text/html; charset=utf-8\r\n\
							Content-Length: " + std::to_string(htmlFile.length()) +
					"\r\n\r\n" + htmlFile.c_str();
			}
			result = send(clientSocket, response.c_str(), response.length(), 0);
			if (result == SOCKET_ERROR) {
				std::cout << "send failed: " << WSAGetLastError() << std::endl;
			}
			std::cout << "Sent bytes: " << result << std::endl;
			closesocket(clientSocket);
		}
	}
	closesocket(listen_socket);
	freeaddrinfo(addr);
	WSACleanup();
	return 0;
}