Ai
1 Star 0 Fork 0

bit.zy/linux_git

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
server.hpp 5.33 KB
一键复制 编辑 原始数据 按行查看 历史
bit.zy 提交于 2023-03-29 15:26 +08:00 . HTTP
#include <iostream>
#include <fstream>
#include <cstdio>
#include <cassert>
#include <cstring>
#include <string>
#include <signal.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
using namespace std;
#define CRLF "\r\n"
#define SPACE " "
#define SPACE_LEN strlen(SPACE)
#define HOME_PAGE "index.html"
#define ROOT_PATH "wwwroot"
// 提取路径
string getPath(string http_request)
{
size_t pos = http_request.find(CRLF);
if (pos == string::npos)
return "";
string request_line = http_request.substr(0, pos); // 请求行
// GET /a/b/c http/1.1
size_t first = request_line.find(SPACE); // 从头开始找
if (pos == string::npos)
return "";
size_t second = request_line.rfind(SPACE); // 从尾开始找
if (second == string::npos)
return "";
// 提取path路径,即两个空格之间的数据
string path = request_line.substr(first + SPACE_LEN, second - (first + SPACE_LEN));
if (path.size() == 1 && path[0] == '/') // 若访问的是根目录,则返回首页
path += HOME_PAGE;
return path;
}
string readFile(const string &recource)
{
ifstream in(recource);
if (!in.is_open())
return "404";
string line;
string content;
while (getline(in, line))
{
content += line;
}
in.close();
return content;
}
void handlerHttpRequest(int sock)
{
char buffer[10240];
ssize_t s = read(sock, buffer, sizeof(buffer));
if (s > 0)
cout << buffer;
// string response = "HTTP/1.1 302 Temporarily Moved\r\n"; // 临时重定向
// string response = "HTTP/1.1 301 Permanently Moved\r\n"; // 永久重定向
// response += "Location: https://www.bilibili.com/\r\n";
// response += "\r\n";
// send(sock, response.c_str(), response.size(), 0);
string path = getPath(buffer);
cout << path << endl;
// path = "/a/b/index.html":请求的人请求的文件路径
// resource = "./wwwroot":我们的web根目录,我们服务器内部给请求的路径自动加上前缀
// resource += path:./wwwroot/a/b/index.html
string recource = ROOT_PATH;
recource += path;
cout << recource <<endl;
string html = readFile(recource);
// 开始响应
string response;
response = "HTTP/1.0 200 OK\r\n";
response += "Content-Type: text/html\r\n";
response += ("Content-Length: " + to_string(html.size()) + "\r\n");
response += "Set-Cookie: this is my cookie content;\r\n";
response += "\r\n"; // 响应报头
response += html; // 正文
send(sock, response.c_str(), response.size(), 0);
}
class ServerTcp
{
public:
ServerTcp(uint16_t port, const string &ip = "")
: port_(port), ip_(ip), listensock_(-1)
{
quit_ = false;
}
~ServerTcp()
{
if (listensock_ >= 0)
close(listensock_);
}
public:
// 初始化
void init()
{
// 1、创建socket
listensock_ = socket(AF_INET, SOCK_STREAM, 0);
if (listensock_ < 0)
{
exit(1);
}
// 2、bind绑定
// 2.1、填充服务器信息
struct sockaddr_in local; // 用户栈
memset(&local, 0, sizeof(local));
local.sin_family = PF_INET;
local.sin_port = htons(port_);
ip_.empty() ? (local.sin_addr.s_addr = INADDR_ANY) : (inet_aton(ip_.c_str(), &local.sin_addr));
// 2.2、将本地socket信息,写入listensock_对应的内核区域
if (bind(listensock_, (const struct sockaddr *)&local, sizeof(local)) == -1)
{
exit(2);
}
// 3、监听socket
if (listen(listensock_, 5) < 0)
{
exit(3);
}
// 允许别人连接你了
}
// 启动服务端
void loop()
{
signal(SIGCHLD, SIG_IGN); // 忽略SIGCHLD信号
while (!quit_)
{
// 4、获取连接
struct sockaddr_in peer;
socklen_t len = sizeof(peer);
int serviceSock = accept(listensock_, (struct sockaddr *)&peer, &len);
if (quit_)
break;
if (serviceSock < 0)
{
cerr << "accept error ...." << endl;
continue;
}
// 5.1 v1.1版本 —— 多进程 ———— 让孙子进程提供服务
// 爷爷进程
pid_t id = fork();
assert(id != -1);
if (id == 0)
{
// 爸爸进程
close(listensock_); // 建议关掉
if (fork() > 0) // 又进行了一次fork,让爸爸进程直接终止
exit(0);
// 孙子进程 ———— 没有爸爸 ———— 孤儿进程 ———— 被系统领养 ———— 回收问题就交给了系统来回收
handlerHttpRequest(serviceSock);
exit(0);
}
close(serviceSock); // 一定要做
// 爸爸进程直接终止,立马得到退出码,释放僵尸状态
wait(nullptr);
}
}
bool quitServer()
{
quit_ = true;
return true;
}
private:
int listensock_; // 监听套接字socket
uint16_t port_; // port
string ip_; // ip
// 安全退出
bool quit_;
};
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C/C++
1
https://gitee.com/bit-zy/linux_git.git
git@gitee.com:bit-zy/linux_git.git
bit-zy
linux_git
linux_git
master

搜索帮助