当前位置: 首页 > news >正文

18.HTTP协议(一)

一.HTTP协议

二.URL的认识

应用层协议往往和端口号是强关联的,比如说http(80),mysql(3306),所以我们不需要体现这个端口号

浏览器会自动添加端口号

当服务器端得到了对应的URL的时候,要将字符重新进行decode(解码)

下面是URL编码的工具,你们可以尝试一下:

https://tool.chinaz.com/Tools/urlencode.aspx

三.HTTP协议请求与响应格式

1.协议的格式(大致了解)

a.Request

本质上http_request就是一个类

b.Response

状态码如404,状态码描述如Not Found

只要我们的数据格式是符合这个协议的,我们就能向浏览器发送请求

2.收发完整性  --  tcp是面向字节流的!

四.http_server封装

1.Socket.hpp的封装

a.Socket设计框架

#pragma once#include <iostream>
#include <string>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>//模板方法模式//基类, 规定创建套接字的方法
class Socket
{
public:virtual ~Socket() = default;virtual int SocketOrDie() = 0;virtual int SetSocketOpt() = 0;virtual bool BindOrDie(int listenscokfd) = 0;virtual bool ListenOrDie(int listenscokfd) = 0;virtual int Accepter(int listenscokfd) = 0;virtual void Close(int fd) = 0;//其他方法,需要时再加//提供一个创建listensockfd的固定实现void BuildTcpSocket(){SocketOrDie();SetSocketOpt();BindOrDie();ListenOrDie();}};class TcpSocket : public Socket
{
public:virtual ~TcpSocket() = default;virtual int SocketOrDie() = 0;virtual int SetSocketOpt() = 0;virtual bool BindOrDie(int listenscokfd) = 0;virtual bool ListenOrDie(int listenscokfd) = 0;virtual int Accepter(int listenscokfd) = 0;virtual void Close(int fd) = 0;private:};int main()
{Socket* sk = new TcpSocket();sk->BuildTcpSocket();
}

b.Socket的实现

#pragma once#include <iostream>
#include <string>
#include <cstdlib>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>#include "Log.hpp"
#include "Common.hpp"
#include "InetAddr.hpp"namespace SocketModule
{using namespace LogModule;// 模板方法模式// 基类, 规定创建套接字的方法class Socket{public:virtual ~Socket() = default;virtual int SocketOrDie() = 0;virtual int SetSocketOpt() = 0;virtual bool BindOrDie(int port) = 0;virtual bool ListenOrDie() = 0;virtual int Accepter() = 0;virtual void Close() = 0;// 其他方法,需要时再加// 提供一个创建listensockfd的固定实现void BuildTcpSocket(int port){SocketOrDie();SetSocketOpt();BindOrDie(port);ListenOrDie();}};class TcpSocket : public Socket{public:TcpSocket():_sockfd(gdefaultsockfd){}virtual ~TcpSocket(){}virtual int SocketOrDie() override{_sockfd = ::socket(AF_INET, SOCK_STREAM, 0);if (_sockfd < 0){LOG(LogLevel::ERROR) << "socket error";exit(SOCKET_ERR);}LOG(LogLevel::DEBUG) << "socket create success: " << _sockfd;}virtual int SetSocketOpt()override{}virtual bool BindOrDie(int port)override{if(_sockfd == gdefaultsockfd){return false;}InetAddr addr(port);int n = ::bind(_sockfd,addr.NetAddr(),addr.NetAddrLen());if(n < 0){LOG(LogLevel::ERROR) << "bind error";exit(BIND_ERR);}LOG(LogLevel::DEBUG) << "bind create success: " << _sockfd;return true;}virtual bool ListenOrDie()override{if(_sockfd == gdefaultsockfd){return false;}int n = ::listen(_sockfd,gbacklog);if(n < 0){LOG(LogLevel::ERROR) << "listen error";exit(LISTEN_ERR);}LOG(LogLevel::DEBUG) << "listen create success: " << _sockfd;return true;}virtual int Accepter()override{}virtual void Close()override{if(_sockfd == gdefaultsockfd){return ;}::close(_sockfd);}private:int _sockfd;};//for testint main(){Socket* sk = new TcpSocket();sk->BuildTcpSocket(8080);}
}

2.TcpServer.hpp的实现

"Socket.hpp"#pragma once#include <iostream>
#include <string>
#include <cstdlib>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>#include "Log.hpp"
#include "Common.hpp"
#include "InetAddr.hpp"namespace SocketModule
{using namespace LogModule;// 模板方法模式using SockPtr = std::shared_ptr<Socket>;// 基类, 规定创建套接字的方法class Socket{public:virtual ~Socket() = default;virtual int SocketOrDie() = 0;virtual int SetSocketOpt() = 0;virtual bool BindOrDie(int port) = 0;virtual bool ListenOrDie() = 0;virtual SockPtr Accepter(InetAddr* client) = 0;virtual void Close() = 0;// 其他方法,需要时再加// 提供一个创建listensockfd的固定实现void BuildTcpSocket(int port){SocketOrDie();SetSocketOpt();BindOrDie(port);ListenOrDie();}};class TcpSocket : public Socket{public:TcpSocket():_sockfd(gdefaultsockfd){}TcpSocket(int sockfd):_sockfd(sockfd){}virtual ~TcpSocket(){}virtual int SocketOrDie() override{_sockfd = ::socket(AF_INET, SOCK_STREAM, 0);if (_sockfd < 0){LOG(LogLevel::ERROR) << "socket error";exit(SOCKET_ERR);}LOG(LogLevel::DEBUG) << "socket create success: " << _sockfd;}virtual int SetSocketOpt()override{}virtual bool BindOrDie(int port)override{if(_sockfd == gdefaultsockfd){return false;}InetAddr addr(port);int n = ::bind(_sockfd,addr.NetAddr(),addr.NetAddrLen());if(n < 0){LOG(LogLevel::ERROR) << "bind error";exit(BIND_ERR);}LOG(LogLevel::DEBUG) << "bind create success: " << _sockfd;return true;}virtual bool ListenOrDie()override{if(_sockfd == gdefaultsockfd){return false;}int n = ::listen(_sockfd,gbacklog);if(n < 0){LOG(LogLevel::ERROR) << "listen error";exit(LISTEN_ERR);}LOG(LogLevel::DEBUG) << "listen create success: " << _sockfd;return true;}//1.文件描述符 2.client infovirtual SockPtr Accepter(InetAddr* client)override{if(!client) return nullptr;struct sockaddr_in peer;socklen_t len = sizeof(peer);int newsockfd = ::accept(_sockfd,CONV(&peer),&len);if(newsockfd < 0){LOG(LogLevel::ERROR) << "accept error";return nullptr;}client->SetAddr(peer,len);return std::make_shared<TcpSocket>(newsockfd);}virtual void Close()override{if(_sockfd == gdefaultsockfd){return ;}::close(_sockfd);}private:int _sockfd;};//for testint main(){Socket* sk = new TcpSocket();sk->BuildTcpSocket(8080);}
}

virtual int Recv(std::string* out)override{char buffer[1024];auto size = ::recv(_sockfd,buffer,sizeof(buffer)-1,0);if(size > 0){buffer[size] = 0;*out = buffer;}return size;}virtual int Send(const std::string& in)override{auto size = ::send(_sockfd,in.c_str(),in.size(),0);return size;}

send和recv方法实现

#pragma once#include <iostream>
#include <memory>
#include <functional>
#include <sys/wait.h>
#include "Socket.hpp"namespace TcpServerModule
{using namespace SocketModule;using namespace LogModule;using tcphandler_t = std::function<bool(SockPtr, InetAddr)>;// 它只负责进行IO,不对协议进行任何的处理class TcpServer{public:TcpServer(int port, tcphandler_t handler) : _listensockp(std::make_unique<TcpSocket>()),_running(false),_handler(handler){_listensockp->BuildTcpSocket(port);}void Loop(){_running = true;while (_running){InetAddr clientaddr;// 1.acceptauto sockfd = _listensockp->Accepter(&clientaddr);if (sockfd == nullptr){continue;}// 2.IO处理LOG(LogLevel::DEBUG) << "get a new client, info is: " << clientaddr.Addr();pid_t id = fork();if (id == 0){_listensockp->Close();if (fork() > 0){exit(0);}_handler(sockfd, clientaddr);exit(0);}sockfd->Close();waitpid(id, nullptr, 0);}_running = false;}~TcpServer(){_listensockp->Close();}private:// 一定要有一个 Listensockstd::unique_ptr<Socket> _listensockp;bool _running;tcphandler_t _handler;};}

3.HttpServer.hpp的实现

#pragma once#include <iostream>
#include <string>
#include "TcpSever.hpp"using namespace TcpServerModule;class HttpServer
{
public:HttpServer(int port):_tsvr(std::make_unique<TcpServer>(port)){}void Start(){_tsvr->InitServer([this](SockPtr sockfd,InetAddr client){return this->HandlerHttpRequest(sockfd,client);});_tsvr->Loop();}bool HandlerHttpRequest(SockPtr sockfd,InetAddr client){LOG(LogLevel::DEBUG) << "HttpServer: get a new client: " << sockfd->Fd() << " addr info: " << client.Addr();return true;}~HttpServer(){}
private:std::unique_ptr<TcpServer> _tsvr;
};

bool HandlerHttpRequest(SockPtr sockfd,InetAddr client){LOG(LogLevel::DEBUG) << "HttpServer: get a new client: " << sockfd->Fd() << " addr info: " << client.Addr();std::string http_request;sockfd->Recv(&http_request);std::cout << http_request;return true;}

我们现在将读到的消息进行打印

4.hello 的网页

bool HandlerHttpRequest(SockPtr sockfd,InetAddr client){LOG(LogLevel::DEBUG) << "HttpServer: get a new client: " << sockfd->Fd() << " addr info: " << client.Addr();std::string http_request;//目前我们读取到的是最原始的信息sockfd->Recv(&http_request);std::cout << http_request;//读取请求,进行文本处理//1.读取请求的完整性  --  暂时不做了//2.完整http反序列化,http response序列化...std::string status_line = "HTTP/1.1 200 OK" + Sep + BlankLine;std::string body = "<!DOCTYPE html>\<html>\<head>\<meta charset = \"UTF-8\">\<title> Hello World</title>\</head>\<body>\<p> Hello World</p>\</body> </html>";std::string httpresponse = status_line + body;sockfd->Send(httpresponse);return true;}

http://www.dtcms.com/a/610046.html

相关文章:

  • 【每天一个AI小知识】:什么是逻辑回归?
  • Moe框架分析
  • Windows下nacos开机自启动
  • C++ 11 中的move赋值运算符
  • Java:startsWith()
  • 【Linux】进程间通信(四)消息队列、信号量与内核管理ipc资源机制
  • php整站最新版本下载html5 网站开发工具
  • wordpress更换网站数据库中国网络公司排名前十
  • 病床脚轮制动系统公差优化:CETOL 6σ建模与装配顺序重构,根治对中漂移
  • 专注网站建设与制作做网站费用多少钱
  • 潍坊网站建设哪家专业门户网站php源码
  • 【架构】安全
  • 大数据生态Sql引擎
  • 使用 .NET 8 构建 RESTful Web API
  • Servlet进阶
  • 计算机视觉——图像数据增强从原理到落地的全解析
  • 【MATLAB例程】2雷达二维目标跟踪滤波系统-UKF(无迹卡尔曼滤波)实现,目标匀速运动模型(带扰动)。附代码下载链接
  • yolov5/8/9/10/11/12/13+deep-oc-sort算法的目标跟踪实现
  • 网站维护花费个人备案网站做app
  • 用Scrapyd爬取豆瓣图书Top250
  • 数据分析笔记06:假设检验
  • 【论文阅读17】-LLM-TSFD:一种基于大型语言模型的工业时间序列人机回路故障诊断方法
  • Elasticsearch 面试题精编(26题|含答案|分类整理)
  • 专业格泰网站建设宝塔 怎么做网站
  • app做好了网站怎么做1千万人网站维护成本
  • 网站设计价格大概多少宁波seo关键词优化服务
  • AIGC总结二:Stable Diffusion 的训练方式、使用流程、硬件要求、实际应用场景
  • 大疆Action 6 ,pocket3及 action 5 Pro 该如何选择?
  • 银川网站开发培训案例分析网站
  • 谷歌云数据库服务概览:关系型与 NoSQL 的多元选择与应用场景解析