I make an HTTP server, or rather a class so that there will always be a high-level tool for this task. But it blocks the program's robot waiting for a request. How to make it so that it does not block the progress of the execution.
#include <iostream> #include <sstream> #include <string> #include <fstream> #include <stdlib.h> #define _WIN32_WINNT 0x501 #include <WinSock2.h> #include <WS2tcpip.h> // ΠΠ΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΠΎ, ΡΡΠΎΠ±Ρ Π»ΠΈΠ½ΠΊΠΎΠ²ΠΊΠ° ΠΏΡΠΎΠΈΡΡ
ΠΎΠ΄ΠΈΠ»Π° Ρ DLL-Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΎΠΉ // ΠΠ»Ρ ΡΠ°Π±ΠΎΡΡ Ρ ΡΠΎΠΊΠ΅ΡΠ°ΠΌ #pragma comment(lib, "Ws2_32.lib") using std::cerr; const int max_client_buffer_size = 1024; char buf[max_client_buffer_size]; int client_socket = INVALID_SOCKET; class HTTPserver { public: bool error; WSADATA wsaData; // ΡΠ»ΡΠΆΠ΅Π±Π½Π°Ρ ΡΡΡΡΠΊΡΡΡΠ° Π΄Π»Ρ Ρ
ΡΠ°Π½Π΅Π½ΠΈΠ΅ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠΈ // ΠΎ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ Windows Sockets // ΡΡΠ°ΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ ΡΠΎΠΊΠ΅ΡΠΎΠ² ΠΏΡΠΎΡΠ΅ΡΡΠΎΠΌ // (ΠΏΠΎΠ΄Π³ΡΡΠΆΠ°Π΅ΡΡΡ Ws2_32.dll) int result;// = WSAStartup(MAKEWORD(2, 2), &wsaData); struct addrinfo* addr;// = NULL; // ΡΡΡΡΠΊΡΡΡΠ°, Ρ
ΡΠ°Π½ΡΡΠ°Ρ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ // ΠΎΠ± IP-Π°Π΄ΡΠ΅ΡΠ΅ ΡΠ»ΡΡΠ°ΡΡΠ΅Π³ΠΎ ΡΠΎΠΊΠ΅ΡΠ° // Π¨Π°Π±Π»ΠΎΠ½ Π΄Π»Ρ ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΠΈ ΡΡΡΡΠΊΡΡΡΡ Π°Π΄ΡΠ΅ΡΠ° struct addrinfo hints; int listen_socket; HTTPserver(char* ip,char *port) { error = false; result = WSAStartup(MAKEWORD(2, 2), &wsaData); // ΠΡΠ»ΠΈ ΠΏΡΠΎΠΈΠ·ΠΎΡΠ»Π° ΠΎΡΠΈΠ±ΠΊΠ° ΠΏΠΎΠ΄Π³ΡΡΠ·ΠΊΠΈ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ if (result != 0) { cerr << "WSAStartup failed: " << result << "\n"; //return result; error = true; return; } addr = NULL; // ΡΡΡΡΠΊΡΡΡΠ°, Ρ
ΡΠ°Π½ΡΡΠ°Ρ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ // Π¨Π°Π±Π»ΠΎΠ½ Π΄Π»Ρ ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΠΈ ΡΡΡΡΠΊΡΡΡΡ Π°Π΄ΡΠ΅ΡΠ° //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(ip, port, &hints, &addr); // ΠΡΠ»ΠΈ ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ ΡΡΡΡΠΊΡΡΡΡ Π°Π΄ΡΠ΅ΡΠ° Π·Π°Π²Π΅ΡΡΠΈΠ»Π°ΡΡ Ρ ΠΎΡΠΈΠ±ΠΊΠΎΠΉ, // Π²ΡΠ²Π΅Π΄Π΅ΠΌ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ΠΌ ΠΎΠ± ΡΡΠΎΠΌ ΠΈ Π·Π°Π²Π΅ΡΡΠΈΠΌ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ if (result != 0) { cerr << "getaddrinfo failed: " << result << "\n"; WSACleanup(); // Π²ΡΠ³ΡΡΠ·ΠΊΠ° Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ Ws2_32.dll //return 1; error = false; return; } // Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΡΠΎΠΊΠ΅ΡΠ° 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; error = false; return; } // ΠΡΠΈΠ²ΡΠ·ΡΠ²Π°Π΅ΠΌ ΡΠΎΠΊΠ΅Ρ ΠΊ 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; error = false; return; } // ΠΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·ΠΈΡΡΠ΅ΠΌ ΡΠ»ΡΡΠ°ΡΡΠΈΠΉ ΡΠΎΠΊΠ΅Ρ if (listen(listen_socket, SOMAXCONN) == SOCKET_ERROR) { cerr << "listen failed with error: " << WSAGetLastError() << "\n"; closesocket(listen_socket); WSACleanup(); // return 1; error = false; return; } //const int max_client_buffer_size = 1024; //char buf[max_client_buffer_size]; client_socket = INVALID_SOCKET; } /*void Scan(std::string (*func)(std::string)) { std::string r = ""; Scan(func, r); }*/ void VerifyR(std::string (*func)(std::string)) { // for (;;) { // ΠΡΠΈΠ½ΠΈΠΌΠ°Π΅ΠΌ Π²Ρ
ΠΎΠ΄ΡΡΠΈΠ΅ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ client_socket = accept(listen_socket, NULL, NULL); if (client_socket == INVALID_SOCKET) { cerr << "accept failed: " << WSAGetLastError() << "\n"; closesocket(listen_socket); WSACleanup(); // return 1; error = false; return; } 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'; // Π€ΠΎΡΠΌΠΈΡΡΠ΅ΠΌ Π²Π΅ΡΡ ΠΎΡΠ²Π΅Ρ Π²ΠΌΠ΅ΡΡΠ΅ Ρ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ°ΠΌΠΈ response << func(buf); // ΠΡΠΏΡΠ°Π²Π»ΡΠ΅ΠΌ ΠΎΡΠ²Π΅Ρ ΠΊΠ»ΠΈΠ΅Π½ΡΡ Ρ ΠΏΠΎΠΌΠΎΡΡΡ ΡΡΠ½ΠΊΡΠΈΠΈ send result = send(client_socket, response.str().c_str(), response.str().length(), 0); if (result == SOCKET_ERROR) { // ΠΏΡΠΎΠΈΠ·ΠΎΡΠ»Π° ΠΎΡΠΈΠ±ΠΊΠ° ΠΏΡΠΈ ΠΎΡΠΏΡΠ°Π²Π»Π΅ Π΄Π°Π½Π½ΡΡ
cerr << "send failed: " << WSAGetLastError() << "\n"; } // ΠΠ°ΠΊΡΡΠ²Π°Π΅ΠΌ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅ ΠΊ ΠΊΠ»ΠΈΠ΅Π½ΡΠΎΠΌ closesocket(client_socket); } } } void Verify(std::string (*func)(std::string)) { // ΠΡΠΈΠ½ΠΈΠΌΠ°Π΅ΠΌ Π²Ρ
ΠΎΠ΄ΡΡΠΈΠ΅ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ client_socket = accept(listen_socket, NULL, NULL); if (client_socket == INVALID_SOCKET) {cerr << "accept failed: " << WSAGetLastError() << "\n"; closesocket(listen_socket); WSACleanup(); error = false; return; } 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) response_body << func(buf); //ByString // Π€ΠΎΡΠΌΠΈΡΡΠ΅ΠΌ Π²Π΅ΡΡ ΠΎΡΠ²Π΅Ρ Π²ΠΌΠ΅ΡΡΠ΅ Ρ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ°ΠΌΠΈ 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); if (result == SOCKET_ERROR) { // ΠΏΡΠΎΠΈΠ·ΠΎΡΠ»Π° ΠΎΡΠΈΠ±ΠΊΠ° ΠΏΡΠΈ ΠΎΡΠΏΡΠ°Π²Π»Π΅ Π΄Π°Π½Π½ΡΡ
cerr << "send failed: " << WSAGetLastError() << "\n"; } // ΠΠ°ΠΊΡΡΠ²Π°Π΅ΠΌ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅ ΠΊ ΠΊΠ»ΠΈΠ΅Π½ΡΠΎΠΌ closesocket(client_socket); } } ~HTTPserver() { // Π£Π±ΠΈΡΠ°Π΅ΠΌ Π·Π° ΡΠΎΠ±ΠΎΠΉ closesocket(listen_socket); freeaddrinfo(addr); WSACleanup(); } }; //ΠΠΎΠ»ΡΡΠΈΡΡ ΠΎΠ΄ΠΈΠ½ ΠΈΠ· ΠΠ ΠΏΠ΅ΡΠ²ΡΠΉ ΠΏΠΎΠΏΠ°Π²ΡΡΠΉΡΡ std::string GetIP() { std::string out = "WinSock ERR"; WSADATA wsaData; if (!WSAStartup(WINSOCK_VERSION, &wsaData)){char chInfo[64]; if (!gethostname(chInfo, sizeof(chInfo))) { hostent *sh; sh=gethostbyname((char*)&chInfo); if (sh!=NULL) { int nAdapter = 0; while (sh->h_addr_list[nAdapter]) { struct sockaddr_in adr; memcpy(&adr.sin_addr, sh->h_addr_list[nAdapter], sh->h_length); out = inet_ntoa(adr.sin_addr); nAdapter++; } } } } WSACleanup(); return out; } //ΠΠΎΠ»ΡΡΠΈΡΡ ΡΠ°ΠΈΠ» Π² ΡΠΎΡΠΌΠ°ΡΠ΅ ΡΡΡΠΎΠΊΠΈ bool getFile(char* url,std::string &r) { r = ""; std::ifstream in(url); if(in) { while(1) { char t; in.get(t); if(in.eof()) break; r+=t; } in.close(); } else return false; return true; } std::string reqset(std::string zapross) { std::string zp; std::ifstream in("index.html"); if(in) { while(1) { char t = in.get(); if(in.eof()) break; zp+=t; } in.close(); } else zp = "Noo File"; zp+="<p>Zapross send v otvet</p>"; zapross; for(int i = 0; i < zapross.size(); i++) { if(zapross[i] != '\n') zp+= zapross[i]; else { zp+= "<p></p>"; } } return zp; } int main() { //ΠΡΠΈΡΠ²ΠΎΠΈΡΡ ΡΠ΅Π°Π»ΡΠ½ΡΡ ip ΠΈΠ· Π°Π΄Π°ΠΏΡΠΎΡΠ° ΠΏΠ΅ΡΠ²ΠΎΠ³ΠΎ std::string sIP = GetIP(); std::cout<<sIP<<'\n'; //Π£ΡΡΠ°Π½ΠΎΠ²ΠΈΡΡ ip ΡΠ΅ΡΠ²Π΅ΡΠ° HTTPserver F((char*)sIP.c_str(),"80"); //ΠΡΠ»ΠΈ ΠΎΡΡΠ±ΠΊΠΈ Π²ΡΡ ΠΊΠΎΠ½Π΅Ρ if(F.error) return 0; while(1) { //ΠΠ°ΠΏΡΡΡΠΈΡΡ Π½Π° ΠΎΠΆΡΠ΄Π°Π½ΠΈΠ΅ Π·Π°ΠΏΡΠΎΡΡΠ° F.Verify(reqset); std::cout<<"------\n"; } return 0; }