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;
}
运行结果
