国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當前位置: 首頁 > news >正文

微信公眾號平臺網(wǎng)站開發(fā)百度天眼查公司

微信公眾號平臺網(wǎng)站開發(fā),百度天眼查公司,做外貿(mào)常用的網(wǎng)站,網(wǎng)站建設(shè)小技巧文章目錄 一、HTTP協(xié)議1.認識URL2.urlencode和urldecode3.HTTP協(xié)議格式4.HTTP的方法5.HTTP的狀態(tài)碼6.HTTP常見Header7.重定向8.長連接9.會話保持10.基本工具 二、簡單的HTTP服務(wù)器實現(xiàn)1.err.hpp2.log.hpp3.procotol.hpp4.Sock.hpp5.Util.hpp6.httpServer.hpp7.httpServer.cc8.總…

文章目錄

  • 一、HTTP協(xié)議
    • 1.認識URL
    • 2.urlencode和urldecode
    • 3.HTTP協(xié)議格式
    • 4.HTTP的方法
    • 5.HTTP的狀態(tài)碼
    • 6.HTTP常見Header
    • 7.重定向
    • 8.長連接
    • 9.會話保持
    • 10.基本工具
  • 二、簡單的HTTP服務(wù)器實現(xiàn)
    • 1.err.hpp
    • 2.log.hpp
    • 3.procotol.hpp
    • 4.Sock.hpp
    • 5.Util.hpp
    • 6.httpServer.hpp
    • 7.httpServer.cc
    • 8.總結(jié)分析

一、HTTP協(xié)議

雖然我們說, 應(yīng)用層協(xié)議是我們程序猿自己定的.

但實際上, 已經(jīng)有大佬們定義了一些現(xiàn)成的, 又非常好用的應(yīng)用層協(xié)議, 供我們直接參考使用. HTTP(超文本傳輸議)就是其中之一。

1.認識URL

平時我們俗稱的 “網(wǎng)址” 其實就是說的 URL

在這里插入圖片描述

2.urlencode和urldecode

像 / ? : 等這樣的字符, 已經(jīng)被url當做特殊意義理解了. 因此這些字符不能隨意出現(xiàn).

比如, 某個參數(shù)中需要帶有這些特殊字符, 就必須先對特殊字符進行轉(zhuǎn)義.

轉(zhuǎn)義的規(guī)則如下:

將需要轉(zhuǎn)碼的字符轉(zhuǎn)為16進制,然后從右到左,取4位(不足4位直接處理),每2位做一位,前面加上%,編成%XY格式

在這里插入圖片描述

“+” 被轉(zhuǎn)義成了 “%2B”

urldecode就是urlencode的逆過程;

encode:對特殊符號和漢字編碼為%XX

decode:服務(wù)器(軟件)收到url請求–自己對特殊%XX進行解碼

urldecode工具

3.HTTP協(xié)議格式

HTTP請求

在這里插入圖片描述

首行: [方法] + [url] + [版本]

Header: 請求的屬性, 冒號分割的鍵值對;每組屬性之間使用\n分隔;遇到空行表示Header部分結(jié)束

Body: 空行后面的內(nèi)容都是Body. Body允許為空字符串. 如果Body存在, 則在Header中會有一個Content-Length屬性來標識Body的長度;

HTTP響應(yīng)

在這里插入圖片描述

首行: [版本號] + [狀態(tài)碼] + [狀態(tài)碼解釋]

Header: 請求的屬性, 冒號分割的鍵值對;每組屬性之間使用\n分隔;遇到空行表示Header部分結(jié)束

Body: 空行后面的內(nèi)容都是Body. Body允許為空字符串. 如果Body存在, 則在Header中會有一個Content-Length屬性來標識Body的長度; 如果服務(wù)器返回了一個html頁面, 那么html頁面內(nèi)容就是在body中

狀態(tài)碼有200,400,302,307,500,404等等

狀態(tài)碼描述:404 -> Not Found 200 -> OK

在這里插入圖片描述

1.請求和響應(yīng)怎么保證應(yīng)用層完整讀取完畢了?

a.首先讀取完整的一行

b.while(讀取完整的一行)-所有的請求行+請求報頭全部讀完-直到空行

c.我們能保證把報頭讀完,報頭有一個屬性:Content-Length:XXX正文長度

d.解析出來內(nèi)容長度,再根據(jù)內(nèi)容長度,讀取正文即可。

2.請求和響應(yīng)是怎么做到序列化和反序列化的?

http自己實現(xiàn)的,第一行+請求/響應(yīng)報頭,只要按照\r\n將字符串1->n即可,正文則不需要做

響應(yīng)的正文可以是html/css/js/圖片/視頻/音頻等

4.HTTP的方法

在這里插入圖片描述

其中最常用的就是GET方法和POST方法.

5.HTTP的狀態(tài)碼

在這里插入圖片描述

最常見的狀態(tài)碼, 比如 200(OK), 404(Not Found), 403(Forbidden), 302(Redirect, 重定向), 504(Bad Gateway)

6.HTTP常見Header

Content-Type: 數(shù)據(jù)類型(text/html等)

Content-Length: Body的長度

Host: 客戶端告知服務(wù)器, 所請求的資源是在哪個主機的哪個端口上;

User-Agent: 聲明用戶的操作系統(tǒng)和瀏覽器版本信息;

referer: 當前頁面是從哪個頁面跳轉(zhuǎn)過來的;

location: 搭配3xx狀態(tài)碼使用, 告訴客戶端接下來要去哪里訪問;

Cookie: 用于在客戶端存儲少量信息. 通常用于實現(xiàn)會話(session)的功能;

7.重定向

我們使用手機或者瀏覽器的時候,屏幕什么也沒有點,就跳轉(zhuǎn)到了其他的頁面,比如自動跳轉(zhuǎn)到廣告商等,這是通過重定向完成的。重定向分為臨時重定向和永久重定向。

重定向過程:客戶端向服務(wù)器發(fā)送http請求,服務(wù)器給客戶端發(fā)送的http響應(yīng)的狀態(tài)碼為3XX,附帶一個新的url,然后客戶端重新向新的服務(wù)器發(fā)起請求—臨時重定向。假如一個公司的一個網(wǎng)站,因為各種原因(比如同時訪問數(shù)量受限等),所以重新寫了一個網(wǎng)站,但是客戶不知道新的網(wǎng)站鏈接,只知道老的鏈接,所以公司對老的鏈接進行永久重定向,客戶在訪問以前的網(wǎng)站的時候自動跳轉(zhuǎn)到新的網(wǎng)站—永久重定向

在這里插入圖片描述

8.長連接

其實我們看到的網(wǎng)頁,實際上可能由多種元素構(gòu)成,即一張完整的網(wǎng)頁需要多次http請求

http網(wǎng)頁中可能包含多個元素,如果頻繁的發(fā)起http請求,http是基于TCP的,TCP是面向連接的,就會有頻繁創(chuàng)建連接的問題(客戶端和服務(wù)器都需要對連接進行管理,先描述再組織,會對連接創(chuàng)建對應(yīng)的內(nèi)核數(shù)據(jù)結(jié)構(gòu),對連接的管理就變成了對數(shù)據(jù)結(jié)構(gòu)的管理,就會有時間和空間的成本)

所以就提出了長連接,長連接需要client和server都要支持,建立好一條連接,獲取一份資源的時候,通過同一條連接來完成

Connection:Keep-alive  --支持長連接
Connection:close   --不支持長連接

9.會話保持

我們使用網(wǎng)頁的bilibili的時候,我們登錄一次之后,后面的一段時間都不需要我們重新進行登錄了,關(guān)閉頁面,然后重新點進去也不需要重新登錄,這就是http的會話保持做到的

會話保持嚴格意義不是http天然具備的,而是后面使用發(fā)現(xiàn)需要的

http協(xié)議是無狀態(tài)的,即http不關(guān)心上一次和下一次的請求,只負責當前請求的傳輸,但是用戶需要,因為用戶查看新的網(wǎng)頁是常規(guī)操作,如果發(fā)送頁面跳轉(zhuǎn),那么新的頁面也就無法識別是哪一個用戶了,為了讓用戶一經(jīng)登錄,可以在整個網(wǎng)站按照自己的身份進行隨意訪問,就需要會話保持。

我們看騰訊視頻的時候,對于需要會員的視頻,我們可以通過鏈接直接獲取而不進行登錄嗎,答案是不行的,凡是對網(wǎng)頁訪問有權(quán)限要求的網(wǎng)頁,在被獲取之前,全部都要做判斷,進行身份認證。

會話保持有兩種方法:

第一種方案:我們在瀏覽器進行登錄輸入信息之后,瀏覽器會把我們用戶輸入的信息:用戶名&&密碼保持起來,這個被稱為cookie數(shù)據(jù)。cookie分為cookie文件級數(shù)據(jù)和cookie內(nèi)存級數(shù)據(jù)。往后只要訪問同一個網(wǎng)站,瀏覽器就會自動推送歷史保留信息給服務(wù)器

我們登錄的時候,瀏覽器保存了cookie文件,每次請求賬號密碼都要進行推送,然后服務(wù)器再返回資源,但是這里有個問題,如果黑客在我們的電腦上種植了木馬病毒,獲取了我們的cookie文件,這樣我們的賬號密碼就泄漏了,那么黑客使用他的瀏覽器登錄我們的賬號,此時服務(wù)器會誤認為這個非法用戶是你,如果是QQ,微信對我們就會造成很大的影響

第二種方案:我們進行登錄的時候輸入用戶名和密碼,此時服務(wù)器端會根據(jù)用戶的信息形成一個session文件,它有唯一的名稱:session id來進行唯一標識,然后將當前用戶的session id返回給用戶,此時瀏覽器的cookie文件中保存的是session id。此后用戶發(fā)送http request 和session id給服務(wù)器,服務(wù)器根據(jù)session id進行鑒權(quán),此時client保存了cookie,server保存了session。

如果黑客獲取了用戶的session,此時服務(wù)器還是會誤認為這個非法用戶是你,但是此時我們已經(jīng)將矛盾轉(zhuǎn)移了,此時黑客盜取的是公司的私密數(shù)據(jù),有法律進行維護,此外還配合了其他的策略來緩解該類問題,比如我們在很短的時間內(nèi)從一個地區(qū)到另一個地區(qū),QQ就會提醒我們異地登錄,需要重新進行登錄等等

10.基本工具

這里介紹兩個基本工具:postman 和 fiddler
在這里插入圖片描述

postman不是抓包工具,而是一個模擬客戶端—瀏覽器的行為的工具

fiddler是一個抓包工具,http工具

postman和fiddler的原理:

瀏覽器將請求發(fā)送給fiddler,此時fiddler可以作為代理服務(wù)器看待,然后就fiddler將請求轉(zhuǎn)發(fā)給服務(wù)器,服務(wù)器響應(yīng)的信息通過fiddler轉(zhuǎn)發(fā)到用戶的手中,而postman則就是相當于客戶端向服務(wù)器發(fā)起請求

我們對下文的程序進行抓包:

我們可以看到,我們的賬號和密碼都是明文的,所以POST和GET都是不安全的,只有是否私密的區(qū)別,安全需要HTTPS來完成。

二、簡單的HTTP服務(wù)器實現(xiàn)

1.err.hpp

#pragma onceenum
{USAGE_ERR = 1,SOCKET_ERR,BIND_ERR,LISTEN_ERR
};

2.log.hpp

#pragma once#include <iostream>
#include <string>
#include <cstdarg>
#include <ctime>
#include <unistd.h>#define DEBUG 0
#define NORMAL 1
#define WARNING 2
#define ERROR 3
#define FATAL 4#define LOG_NORMAL "log.txt"
#define LOG_ERR "log.error"#define NUM 1024const char *to_levelstr(int level)
{switch (level){case DEBUG:return "DEBUG";case NORMAL:return "NORMAL";case WARNING:return "WARNING";case ERROR:return "ERROR";case FATAL:return "FATAL";default:return nullptr;}
}void logMessage(int level, const char *format, ...)
{char logprefix[NUM];snprintf(logprefix, sizeof(logprefix), "[%s][%ld][pid: %d]",to_levelstr(level), (long int)time(nullptr), getpid());char logcontent[NUM];va_list arg;va_start(arg, format);vsnprintf(logcontent, sizeof(logcontent), format, arg);std::cout << logprefix << logcontent << std::endl;FILE *log = fopen(LOG_NORMAL, "a");FILE *error = fopen(LOG_ERR, "a");if (log && error){FILE *cur = nullptr;if (level == DEBUG || level == NORMAL || level == WARNING)cur = log;if (level == ERROR || level == FATAL)cur = error;if (cur)fprintf(cur, "%s%s\n", logprefix, logcontent);fclose(log);fclose(error);}
}

3.procotol.hpp

#pragma once#include <iostream>
#include <string>
#include <sstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "Util.hpp"const std::string sep = "\r\n";
const std::string default_root = "./wwwroot";
const std::string home_page = "index.html";
const std::string html_404 = "wwwroot/404.html";class HttpRequest
{
public:HttpRequest() {}~HttpRequest() {}public:void parse(){// 1. 從inbuffer中拿到第一行,分隔符\r\nstd::string line = Util::getOneLine(inbuffer, sep);if (line.empty())return;// 2. 從請求行中提取三個字段// std::cout << "line: " << line << std::endl;std::stringstream ss(line);ss >> method >> url >> httpversion;// 3. 添加web默認路徑path = default_root; // ./wwwroot,path += url;         //./wwwroot/a/b/c.html, ./wwwroot/if (path[path.size() - 1] == '/')path += home_page;// 4.獲取path對應(yīng)資源的后綴// ./wwwroot.index.html// ./wwwroot.1.jpgauto pos = path.rfind(".");if (pos == std::string::npos)suffix = ".html";elsesuffix = path.substr(pos);// 5.得到資源的大小struct stat st;int n = stat(path.c_str(), &st);if (n == 0)size = st.st_size;elsesize = -1;}public:std::string inbuffer;std::string method;std::string url;std::string httpversion;std::string path;std::string suffix;int size;
};class HttpResponse
{
public:std::string outbuffer;
};

4.Sock.hpp

#pragma once#include <iostream>
#include <string>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>#include "log.hpp"
#include "err.hpp"static const int backlog = 5;class Sock
{
public:void Socket(){_listensock = socket(AF_INET, SOCK_STREAM, 0);if (_listensock < 0){logMessage(FATAL, "create socket error");exit(SOCKET_ERR);}int opt = 1;setsockopt(_listensock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof opt);logMessage(NORMAL, "create socket success");}void Bind(const uint16_t &port){struct sockaddr_in local;memset(&local, 0, sizeof local);local.sin_family = AF_INET;local.sin_addr.s_addr = INADDR_ANY;local.sin_port = htons(port);int n = bind(_listensock, (struct sockaddr *)&local, sizeof local);if (n < 0){logMessage(FATAL, "bind socket error");exit(BIND_ERR);}logMessage(NORMAL, "bind socket success");}void Listen(){int n = listen(_listensock, backlog);if (n < 0){logMessage(FATAL, "listen socket error");exit(LISTEN_ERR);}logMessage(NORMAL, "listen socket success");}int Accept(){struct sockaddr_in peer;socklen_t len = sizeof(peer);int sock = accept(_listensock, (struct sockaddr *)&peer, &len);return sock;}int Fd(){return _listensock;}void Close(){if (_listensock > 0)close(_listensock);}private:int _listensock;
};

5.Util.hpp

#pragma once#include <string>
#include <fstream>class Util
{
public:static std::string getOneLine(std::string &buffer, const std::string &sep){auto pos = buffer.find(sep);if (pos == std::string::npos)return "";std::string sub = buffer.substr(0, pos);buffer.erase(0, sub.size() + sep.size());return sub;}static bool readFile(const std::string resource, char *buffer, int size){std::ifstream in(resource, std::ios::binary);if (!in.is_open())return false;in.read(buffer, size);in.close();return true;}
};

6.httpServer.hpp

#pragma once #include <functional>
#include <sys/wait.h>
#include "Sock.hpp"
#include "protocol.hpp"
#include "log.hpp"
#include "err.hpp"
#include "Util.hpp"namespace server
{static const int defaultport = 8080;using func_t = std::function<bool(const HttpRequest &, HttpResponse &)>;class httpServer{public:httpServer(const func_t func, const uint16_t &port = defaultport): _func(func), _port(port){}void initServer(){_sock.Socket();_sock.Bind(_port);_sock.Listen();}void handlerEvent(int sock){// 1. 讀到完整的http請求// 2. 反序列化// 3. httprequst, httpresponse, _func(req, resp)// 4. resp序列化// 5. sendchar buffer[4096];HttpRequest req;HttpResponse resp;size_t n = recv(sock, buffer, sizeof(buffer) - 1, 0);if (n > 0){buffer[n] = 0;req.inbuffer = buffer;req.parse();_func(req, resp); // req -> respsend(sock, resp.outbuffer.c_str(), resp.outbuffer.size(), 0);}}void start(){for (;;){int sock = _sock.Accept();if (sock < 0)continue;pid_t id = fork();if (id == 0){_sock.Close();if (fork() > 0)exit(0);handlerEvent(sock);close(sock);exit(0);}close(sock);waitpid(id, nullptr, 0);}}~httpServer(){}private:Sock _sock;uint16_t _port;func_t _func;};
}

7.httpServer.cc

#include "httpServer.hpp"
#include <memory>using namespace std;
using namespace server;void Usage(std::string proc)
{cerr << "Usage:\n\t" << proc << " port\r\n\r\n";
}std::string suffixToDesc(const std::string suffix)
{std::string ct = "Content-Type: ";if (suffix == ".html")ct += "text/html";else if (suffix == ".jpg")ct += "application/x-jpg";ct += "\r\n";return ct;
}// 1. 服務(wù)器和網(wǎng)頁分離,html
// 2. url -> / : web根目錄
bool Get(const HttpRequest &req, HttpResponse &resp)
{// for testcout << "----------------------http start---------------------------" << endl;cout << req.inbuffer;std::cout << "method: " << req.method << std::endl;std::cout << "url: " << req.url << std::endl;std::cout << "httpversion: " << req.httpversion << std::endl;std::cout << "path: " << req.path << std::endl;std::cout << "suffix: " << req.suffix << std::endl;std::cout << "size: " << req.size << "字節(jié)" << std::endl;cout << "----------------------http end---------------------------" << endl;// std::string respline = "HTTP/1.1 200 OK\r\n";std::string respline = "HTTP/1.1 307 Permanent Redirect\r\n";std::string respheader = suffixToDesc(req.suffix);respheader += "Location: https://www.qq.com/\r\n";std::string respblank = "\r\n";// std::string body = "<html lang=\"en\"><head><meta charset=\"UTF-8\"><title>for test</title><h1>hello world</h1></head><body><p>多情只有春庭月,猶為離人照落花</p></body></html>";std::string body;body.resize(req.size + 1);if (!Util::readFile(req.path, (char *)body.c_str(), req.size)){Util::readFile(html_404, (char *)body.c_str(), req.size);}respheader += "Content-Length: ";respheader += to_string(body.size());respheader += "\r\n";resp.outbuffer += respline;resp.outbuffer += respheader;resp.outbuffer += respblank;cout << "----------------------http response start---------------------------" << endl;std::cout << "resp.outbuffer" << resp.outbuffer << std::endl;cout << "----------------------http response end---------------------------" << endl;resp.outbuffer += body;return true;
}// ./httpServer port
int main(int argc, char *argv[])
{// if(argc != 2)// {//     Usage(argv[0]);//     exit(0);// }// uint16_t port = atoi(argv[1]);// unique_ptr<httpServer> httpsvr(new httpServer(Get, port));unique_ptr<httpServer> httpsvr(new httpServer(Get));httpsvr->initServer();httpsvr->start();return 0;
}

8.總結(jié)分析

一個用戶看到的網(wǎng)頁結(jié)果,可能是多個資源結(jié)合而成的,所以要獲取一個網(wǎng)頁效果,我們的瀏覽器一定會 發(fā)起多次http請求。

我們進行數(shù)據(jù)提交的時候,本質(zhì)前端要通過form表單提交的,瀏覽器會自動將form表單中的內(nèi)容轉(zhuǎn)換成GET/POST方法請求

GET和POST的區(qū)別

如下是GET的方式

在這里插入圖片描述

如下是POST的方式

在這里插入圖片描述

二者的區(qū)別如下:

GET通過URL傳遞參數(shù),具體:http://ip:port/XXX/YYY?name=value&name1=value1

POST提交參數(shù)通過http請求的正文提交參數(shù)

POST方法通過正文的提交參數(shù),所以一般用戶看不到,私密性更好,私密性 != 安全性,GET方法不私密

無論是GET還是POST方法,都不安全,要談安全,必須加密 --https

通過URL傳遞參數(shù),注定了不能太大

但是POST方法,通過正文,正文可以很大,甚至可以是其他的東西

http://m.aloenet.com.cn/news/30671.html

相關(guān)文章:

  • 用ps怎樣做網(wǎng)站文字logo廣豐網(wǎng)站seo
  • 個人怎么做貸款網(wǎng)站求購買鏈接
  • 網(wǎng)站權(quán)重高+做別的關(guān)鍵詞百度應(yīng)用下載安裝
  • 學做效果圖網(wǎng)站有哪些軟件有哪些網(wǎng)站建站方式有哪些
  • 有沒有做數(shù)學題掙錢的網(wǎng)站艾滋病多久可以查出來
  • 網(wǎng)站建設(shè)網(wǎng)站軟件有哪些方面深圳網(wǎng)站建設(shè)公司
  • 湖南住房和城鄉(xiāng)建設(shè)廳網(wǎng)站首頁優(yōu)化網(wǎng)站怎么真實點擊
  • 男女做a視頻網(wǎng)站seo1搬到哪里去了
  • wordpress 網(wǎng)站日志天門seo
  • 福建省住建廳建設(shè)網(wǎng)站競價培訓班
  • 手機網(wǎng)站開發(fā)學習免費單頁網(wǎng)站在線制作
  • 可以用足球做的游戲視頻網(wǎng)站好的競價賬戶托管外包
  • 常規(guī)做網(wǎng)站要在工信部認證嗎網(wǎng)站建立
  • 適合個人做的網(wǎng)站有哪些東西嗎百度權(quán)重批量查詢
  • 英語機構(gòu)網(wǎng)站建設(shè)方案足球進球排行榜
  • 做網(wǎng)站的困難windows優(yōu)化大師會員兌換碼
  • 做網(wǎng)站學什么專業(yè)防惡意點擊軟件
  • 南寧網(wǎng)站建設(shè)設(shè)計制作今日最新抗疫數(shù)據(jù)
  • 做代購有哪些網(wǎng)站有哪些seo優(yōu)化培訓課程
  • 做聊天網(wǎng)站的視頻教程怎么進行網(wǎng)站關(guān)鍵詞優(yōu)化
  • wordpress主題如何修改seo優(yōu)化設(shè)計
  • 做網(wǎng)站需要注意的點抖音seo供應(yīng)商
  • 山西成寧做的網(wǎng)站運營推廣渠道有哪些
  • wordpress下載站源碼營銷推廣公司案例
  • 安徽建筑大學學工在線網(wǎng)站蘇州網(wǎng)站制作推廣
  • 廣西代理網(wǎng)站建設(shè)公司百度網(wǎng)址提交入口
  • 做網(wǎng)站建設(shè)站長工具櫻花
  • 甘肅網(wǎng)站建設(shè)制作商競價賬戶托管公司
  • 網(wǎng)站開發(fā)集成環(huán)境seo優(yōu)化工作怎么樣
  • 網(wǎng)站建設(shè)招標評分標準福州網(wǎng)站制作推廣