Http服务器-第二步支持单纯的文件请求
实现完整的网页浏览支持
#include <iostream> #include <list> #include <string> #include <algorithm> #include <vector> #include <thread> #include <fstream> #include <stdlib.h> #include <stdio.h> /* #include <functional> #include "direct.h" #include <map> #include <memory> #include <queue> #include <condition_variable> #include <mutex> #include <atomic> #include <unordered_map> */ #include "winsock.h" #include "stdlib.h" #include "stdio.h" #include "string.h" #pragma comment (lib,"wsock32") using namespace std; typedef struct { int size; unsigned char *buffer; }FileData; typedef struct { int client; int size; unsigned char *buffer; }SendBuffer; class FileReader { public: ~FileReader() { if (this->data.buffer) delete this->data.buffer; } FileReader(string &fileName) { this->name = fileName; memset((void*)&this->data, 0, sizeof(FileData)); } bool ReadFile() { FILE *file = fopen(this->name.c_str(), "rb"); if (!file) { cout << " error open file : " << name << endl; return false; } cout << name << endl; fseek(file, 0, SEEK_END); int size = ftell(file); fseek(file, 0, SEEK_SET); unsigned char *buf = new unsigned char[size]; fread(buf, size, 1, file); this->data.size = size; this->data.buffer = buf; fclose(file); return true; } string name; string rb; FILE* file; FileData data; }; void SendThread(void*arg1, void*arg2) { SendBuffer *buf = (SendBuffer*)arg1; SendBuffer *buf1 = (SendBuffer*)arg2; send(buf->client, (const char*)buf->buffer, buf->size, 0); send(buf1->client, (const char*)buf1->buffer, buf1->size, 0); closesocket(buf->client); delete buf1->buffer; delete buf1; delete buf; } int main() { WSADATA wsadata; WORD wVersion = MAKEWORD(2, 0); WSAStartup(wVersion, &wsadata); int sock, length; length = sizeof(sockaddr); struct sockaddr_in server_ipaddr, client_ipaddr; memset(&server_ipaddr, 0, length); server_ipaddr.sin_family = AF_INET; server_ipaddr.sin_port = htons(80); server_ipaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); char buff[4096]; int nbuff; sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); ::bind(sock, (sockaddr *)&server_ipaddr, length); listen(sock, 180); char *head = "HTTP/1.0 200 OK\n" "Content-Type: text/html\n\n"; char *head_js = "HTTP/1.0 200 OK\n" "Content-Type: application/x-javascript\n\n"; char *head_css = "HTTP/1.0 200 OK\n" "Content-Type: text/css\n\n"; char *head_png = "HTTP/1.0 200 OK\n" "Content-Type: image/png\n\n"; char *head_jpg = "HTTP/1.0 200 OK\n" "Content-Type: image/jpeg\n\n"; char *head_exe = "HTTP/1.0 200 OK\n" "Content-Type: application/x-msdownload\n\n"; char *html1 = "<html><head><title>我的第一个 HTML 页面</title></head><body>"; char * p = "<p>body 元素的内容会显示在浏览器中。</p>"; char *html2 = "<p>title 元素的内容会显示在浏览器的标题栏中。</p>" "</body></html>"; std::cout << "start server ok" << std::endl; int sock_client, len; while (1) { sock_client = accept(sock, (sockaddr *)&client_ipaddr, &length); if (sock_client == SOCKET_ERROR) { WSACleanup(); goto RETURN; } len = recv(sock_client, buff, 4095, 0); buff[len] = '\0'; std::string s = buff; if (!s.size()) { continue; } s = s.substr(0, s.find("\n")); int i = s.find(" ", 0); std::string type = s.substr(0, i++); std::string req = s.substr(i, s.find(" ", i) - i); cout << req << endl; req = req.substr(1, -1); req = req.substr(0, req.find('?')); fstream file; file.open(req, ios::in); s = req; char *h = head; if (s.find(".css") != string::npos) { h = head_css; } if (s.find(".js") != string::npos) { h = head_js; }if (s.find(".html") != string::npos) { h = head; } if (s.find(".png") != string::npos) { h = head_png; } if (s.find(".jpg") != string::npos) { h = head_jpg; } if (s.find(".exe") != string::npos) { h = head_exe; } FileReader* reader = new FileReader(req); reader->ReadFile(); SendBuffer *sb = new SendBuffer; sb->size = strlen(h); sb->buffer = (unsigned char*)h; sb->client = sock_client; SendBuffer *sb2 = new SendBuffer; sb2->size = reader->data.size; sb2->buffer = (unsigned char*)reader->data.buffer; sb2->client = sock_client; std::thread t(SendThread, sb, sb2); t.detach(); cout << endl; } RETURN: system("pause"); return 0; }
运行结果