网络通信:http协议

这篇具有很好参考价值的文章主要介绍了网络通信:http协议。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

虽然我们说, 应用层协议是我们程序猿自己定的. 但实际上, 已经有大佬们定义了一些现成的, 又非常好用的应用层协议, 供我们直接参考使用. HTTP(超文本传输协议) 就是其中之一.

认识URL

统一资源定位符(Uniform Resource Locator,缩写:URL),是对资源的引用和访问该资源的方法。俗称网址。

网络通信:http协议

网络通信:http协议

  • 主机名:表示IP地址的注册名称(域名)或IP地址,用于识别连接到网络设备的数字标识符
  • 端口:跟在域名后面,不是一个URL必须的部分,如果省略端口会使用默认端口。
80是http协议的默认端口,是在输入网站的时候其实浏览器(非IE)已经帮你输入协议了,所以你输入 http://baidu.com,其实是访问 http://baidu.com:80。而8080,一般用与webcahe,完全不一样的两个,比如linux服务器里 apache默认跑80端口,而apache-tomcat默认跑 8080端口,其实端口没有实际意义只是一个接口,主要是看服务的 监听端口。
  • 路径:表示服务器上资源的路径,过去这样的路径标记的是服务器上文件的物理路径,但是现在,路径表示的只是一个抽象地址,并不指代任何物理地址.
  • 参数:请求里提供的额外参数.这些参数是以键值对的形式,通过&符号分隔开来,服务器可以通过这些参数进行相应的个性化处理
  • :用于为页面上的标题提供快速链接,如锚点链接

 urlencode和urldecode

像 / ? : 等这样的字符, 已经被url当做特殊意义理解了. 因此这些字符不能随意出现. 比如, 某个参数中需要带有这些特殊字符, 就必须先对特殊字符进行转义.

转义的规则如下: 将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY 格式

leetcode中文C++   被转义成了   leetcode%E4%B8%AD%E6%96%87C%2B%2B

HTTP协议

网络通信:http协议

HTTP的方法 

网络通信:http协议

 网络通信:http协议

创建html文件,输入!并按tab键,可以得到一个简单的模板。

传输正文时中英文会乱码:

在html文件的头标签中加入<meta charset="UTF-8">

添加一个报头  Content-type: text/html

要获取文件信息可以使用stat接口:

网络通信:http协议

网络通信:http协议

//以文件尺寸为例
struct stat st;
int n = stat(path.c_str(), &st);
if(n == 0) size = st.st_size;
else size = -1;  

 网页教程详情见:w3cschool官网 - 编程狮,随时随地学编程

在Linux中可以使用

wget  [域名]  

获取网页数据。

一个简单的网站服务器

Util.hpp

#pragma once

#include <iostream>
#include <string>
#include<fstream>
using namespace std;

class Util
{
public:
    // XXXX XXX XXX\r\nYYYYY
    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 string& name, string& body)
    {
        auto pos = name.find(".");
        string typeofFile = name.substr(pos);
        ifstream fs(name, fstream::in | fstream::binary);
        char c;
        while(fs.get(c))
        {
            body += c;
        }

        fs.close();

        return true;

    }
};

Protocal.hpp

#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include "Util.hpp"

const std::string sep = "\r\n";
const std::string default_root = "./wwwroot";
const std::string home_page = "index.html";

class HttpRequest
{
public:
    HttpRequest(){}
    ~HttpRequest(){}
    void parse()
    {
        // 1. 从inbuffer中拿到第一行,分隔符\r\n
        std::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对应的资源后缀
        // ./wwwroot/index.html
        // ./wwwroot/test/a.html
        // ./wwwroot/image/1.jpg
        auto pos = path.rfind(".");
        if (pos == std::string::npos)
            suffix = ".html";
        else
            suffix = path.substr(pos);
    }
public:
    std::string inbuffer;
    // std::string reqline;
    // std::vector<std::string> reqheader;
    // std::string body;

    std::string method;
    std::string url;
    std::string httpversion;
    std::string path;
    std::string suffix;
};


class HttpResponse
{
public:
    std::string outbuffer;
};

httpServer.hpp

#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <functional>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include "Protocol.hpp"

namespace server
{    
    enum
    {
        USAGE_ERR = 1,
        SOCKET_ERR,
        BIND_ERR,
        LISTEN_ERR
    };

    static const uint16_t gport = 8080;
    static const int gbacklog = 5;

    using func_t = std::function<bool (const HttpRequest &, HttpResponse &)>;

    class HttpServer
    {
    public:
        HttpServer(func_t func, const uint16_t &port = gport) : _func(func), _listensock(-1), _port(port)
        {
        }
        void initServer()
        {
            // 1. 创建socket文件套接字对象
            _listensock = socket(AF_INET, SOCK_STREAM, 0);
            if (_listensock < 0)
            {
                exit(SOCKET_ERR);
            }

            // 2. bind绑定自己的网络信息
            struct sockaddr_in local;
            memset(&local, 0, sizeof(local));
            local.sin_family = AF_INET;
            local.sin_port = htons(_port);
            local.sin_addr.s_addr = INADDR_ANY;
            if (bind(_listensock, (struct sockaddr *)&local, sizeof(local)) < 0)
            {
                exit(BIND_ERR);
            }

            // 3. 设置socket 为监听状态
            if (listen(_listensock, gbacklog) < 0) // 第二个参数backlog后面在填这个坑
            {
                exit(LISTEN_ERR);
            }
        }
        void HandlerHttp(int sock)
        {
            // 1. 读到完整的http请求
            // 2. 反序列化
            // 3. httprequst, httpresponse, _func(req, resp)
            // 4. resp序列化
            // 5. send
            char buffer[4096];
            HttpRequest req;
            HttpResponse resp;
            size_t n = recv(sock, buffer, sizeof(buffer)-1, 0); // 大概率我们直接就能读取到完整的http请求
            if(n > 0)
            {
                buffer[n] = 0;
                req.inbuffer = buffer;
                req.parse();
                _func(req, resp); // req -> resp
                send(sock, resp.outbuffer.c_str(), resp.outbuffer.size(), 0);
            }
        }
        void start()
        {
            for (;;)
            {
                // 4. server 获取新链接
                // sock, 和client进行通信的fd
                struct sockaddr_in peer;
                socklen_t len = sizeof(peer);
                int sock = accept(_listensock, (struct sockaddr *)&peer, &len);
                if (sock < 0)
                {
                    continue;
                }

                // version 2 多进程版(2)
                pid_t id = fork();
                if (id == 0) // child
                {
                    close(_listensock);
                    if(fork()>0) exit(0);
                    HandlerHttp(sock);
                    close(sock);
                    exit(0);
                }
                close(sock);

                // father
                waitpid(id, nullptr, 0);
            }
        }
        ~HttpServer() {}

    private:
        int _listensock; // 不是用来进行数据通信的,它是用来监听链接到来,获取新链接的!
        uint16_t _port;
        func_t _func;
    };

} // namespace server

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";
}
// 1. 服务器和网页分离,html
// 2. url -> / : web根目录
bool Get(const HttpRequest &req, HttpResponse &resp)
{
    // for test
    cout << "----------------------http start---------------------------" << endl;
    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;

    cout << req.inbuffer << std::endl;
    cout << "----------------------http end---------------------------" << endl;

    std::string respline = "HTTP/1.1 200 OK\r\n";
    std::string respheader = "Content-Type: ";
    if (req.suffix == ".html")
        respheader += "text/html";
    else if (req.suffix == ".jpg")
        respheader += "application/x-jpg;image/jpeg";
    respheader += "\r\n";

    std::string respblank = "\r\n";

    std::string body;
    if(!Util::ReadFile(req.path, body))
    {
        Util::ReadFile("./wwwroot/404.html", body);
    }
    resp.outbuffer += respline;
    resp.outbuffer += respheader;
    resp.outbuffer += respblank;
    resp.outbuffer += body;

    return true;
}

// ./httpServer 8080
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));
    httpsvr->initServer();
    httpsvr->start();

    return 0;
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>main tittle</title>
</head>
<body>
    <h1>每天都刷leetcode</h1>
    <img src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F83b66036-a374-424f-ab45-4a02aaf45a4f%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1688195268&t=19cab953a51d9bd85e9b057dc82d7345" alt="测试图片">
    <img src="/image/1.jpg" alt="本地图片">
    <img src="/image/2.jpg" alt="石榴花">
    <a href="/test/a.html">新闻</a>
    <a href="/test/c.html">电商</a>
</body>
</html>

3开头的状态——重定向

重定向流程图:

网络通信:http协议

实现一个简单的临时重定向:

1.将服务器返回的状态行改为

std::string respline = "HTTP/1.1 307 Temporary Redirect\r\n";

 2.在响应报头中加入重定向的域名

respheader += "Location: https://www.qq.com/\r\n";

浏览器在访问我们的服务器时会自动跳转到QQ。

表单

<form action="/a/b/c.py" method="POST">

姓名:<br> <input type="text" name="xname"> <br>

密码:<br> <input type="password" name="ypwd"> <br>

<br> <input type="submit" value="登陆">

</form>

网络通信:http协议

 使用GET方法和POST方法的区别:

网络通信:http协议

http长连接

HTTP长连接(HTTP keep-alive)是一种在单个TCP连接上可以发送多个HTTP请求和响应的机制。它的主要目的是减少建立和关闭TCP连接的开销,提高性能和效率。

在传统的HTTP协议中,每个HTTP请求都需要建立一个TCP连接,并在请求完成后关闭连接。这意味着在请求的过程中,需要进行多次TCP的三次握手和四次挥手,这些操作会带来一定的开销。而HTTP长连接通过在同一个TCP连接上发送多个HTTP请求,可以避免这些开销,从而提高网络性能。

HTTP长连接的实现方式如下:

  1. 建立连接:客户端通过发送一个HTTP请求到服务器来建立TCP连接。在请求头中包含"Connection: keep-alive"字段,告诉服务器希望使用长连接。

  2. 多个请求:在建立连接后,客户端可以通过同一个TCP连接发送多个HTTP请求。每个请求都与传统的HTTP请求相同,包括请求行、请求头和请求体。

  3. 响应:服务器接收到每个请求后,会发送对应的HTTP响应给客户端。每个响应包括响应行、响应头和响应体。

  4. 连接保持:在响应完成后,TCP连接并不关闭,而是继续保持打开状态。这样客户端可以通过这个连接发送下一个HTTP请求,而无需重新建立连接。

  5. 关闭连接:当客户端不再需要与服务器通信时,可以发送一个特殊的HTTP请求来关闭连接。在请求头中设置"Connection: close"字段,服务器收到该请求后会关闭TCP连接。

需要注意的是,尽管HTTP长连接可以在一个TCP连接上发送多个请求和响应,但服务器和客户端都需要注意适当的管理连接,以避免连接过多导致资源浪费。一般来说,服务器会根据一定的策略(如超时时间)来关闭闲置的连接,或者客户端可以在不使用连接时主动关闭连接。

HTTP长连接在减少网络延迟和提高性能方面具有显著的优势,特别是对于频繁请求的场景,例如网页浏览和API调用等。然而,需要注意的是,长时间的连接可能会占用服务器资源,因此在设计和实现时需要权衡和优化。

http会话保持

HTTP协议是无状态的,但是我们在网站上登陆,浏览器会保持登陆状态,这就是会话保持实现的。

那么服务器是如何识别用户的。

浏览器将用户信息保留,访问同一个网站时自动推送(cookie技术)

网络通信:http协议

cookie文件由客户端维护,会被木马盗取。

新方法:服务端chanssession文件(包含用户信息——账号密码)和session id,浏览器保持session id发送请求时推送id。 

postman和fiddler

postman和fiddler都是调试工具。

postman(模拟浏览器)查看网络信息。

Fiddler是抓包工具,相当于作为浏览器的代理,隔绝的浏览器和服务器。文章来源地址https://www.toymoban.com/news/detail-467802.html

到了这里,关于网络通信:http协议的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java中网络的基本介绍。网络通信,网络,ip地址,域名,端口,网络通信协议,TCP/IP传输过程,网络通信协议模型,TCP协议,UDP协议

    - 网络通信 概念:网络通信是指 通过计算机网络进行信息传输的过程 ,包括数据传输、语音通话、视频会议等。在网络通信中,数据被分成一系列的数据包,并通过网络传输到目的地。在数据传输过程中,需要确保数据的完整性、准确性和安全性。常见的网络通信协议有T

    2024年02月10日
    浏览(50)
  • 10 - 网络通信优化之通信协议:如何优化RPC网络通信?

    微服务框架中 SpringCloud 和 Dubbo 的使用最为广泛,行业内也一直存在着对两者的比较,很多技术人会为这两个框架哪个更好而争辩。 我记得我们部门在搭建微服务框架时,也在技术选型上纠结良久,还曾一度有过激烈的讨论。当前 SpringCloud 炙手可热,具备完整的微服务生态,

    2024年02月11日
    浏览(23)
  • 【网络】应用层——HTTP协议

    🐱作者:一只大喵咪1201 🐱专栏:《网络》 🔥格言: 你只管努力,剩下的交给时间! 上篇文章中,本喵带着大家对HTTP有了一个初步的认识,今天就来详细讲解一下这个应用层协议。 如上图所示的 url (网址),里面包含有 / 以及 ? 等字符。 像这样的字符,已经被url当做 特殊

    2024年02月15日
    浏览(23)
  • 网络通信与网络协议

    网络编程是指利用计算机网络实现程序之间通信的一种编程方式。在网络编程中,程序需要通过网络协议(如 TCP/IP)来进行通信,以实现不同计算机之间的数据传输和共享。 在网络编程中,通常有三个基本要素 IP 地址:定位网络中某台计算机 端口号port:定位计算机上的某个进程

    2024年03月18日
    浏览(39)
  • 【计算机网络】应用层协议 -- HTTP协议

    协议。网络协议的简称,网络协议是通信计算机双方必须共同遵守的一组约定,比如怎么建立连接,怎么互相识别等。 为了使数据在网络上能够从源头到达目的,网络通信的参与方必须遵守相同的规则,我们称这套相同的规则为协议(protocol),而协议最终都需要通过计算机

    2024年02月15日
    浏览(31)
  • 【网络原理】网络通信与协议

    ✨个人主页:bit me👇 ✨当前专栏:Java EE初阶👇 独立模式 :计算机之间相互独立 网络互连 : 随着时代的发展,越来越需要计算机之间互相通信,共享软件和数据,即以多个计算机协同工作来完成业务,就有了网络互连。   网络互连:将多台计算机连接在一起,完成数据共

    2023年04月09日
    浏览(43)
  • 网络协议(七)应用层-HTTP

    上篇文章介绍了传输层的TCP、UDP协议,在TCP/IP协议中,下三层(网络接口层,网络层,传输层)都是计算机系统联合其他硬件设备自己在干的事,身为程序员的我们平时对其感知不大。而应用层却是与程序开发息息相关的一层,如HTTP,HTTPS,DNS,FTP,SMTP等等,针对不同应用场

    2024年02月03日
    浏览(27)
  • 【应用层】网络基础 -- HTTP协议

    协议是一种 “约定”. socket api的接口,在读写数据时,都是按 “字符串” 的方式来发送接收的(tcp是以字节流的方式发送的,这里便与表述使用\\\"字符串\\\") 如果我们要传输一些\\\"结构化的数据\\\" 怎么办呢? 那么我们(TCP)在收到一个报文的时候,如何保证你收到了一个完整的报文?

    2024年02月11日
    浏览(29)
  • 【网络原理】网络通信,网络协议,协议分层,网络设备的分层,封装和分用

    前言: 大家好,我是 良辰丫 ,今天我们一起来学习网络原理,了解一些网络的基本知识以及面试题.💞💞💞 🧑个人主页:良辰针不戳 📖所属专栏:javaEE初阶 🍎励志语句:生活也许会让我们遍体鳞伤,但最终这些伤口会成为我们一辈子的财富。 💦期待大家三连,关注,点赞,

    2023年04月14日
    浏览(43)
  • 《网络协议》05. 网络通信安全 · 密码技术

    title: 《网络协议》05. 网络通信安全 · 密码技术 date: 2022-09-10 15:16:15 updated: 2023-11-12 07:03:52 categories: 学习记录:网络协议 excerpt: 网络通信安全(ARP 欺骗,DoS DDoS,SYN 洪水攻击,LAND 攻击,DNS 劫持,HTTP 劫持)、密码技术(单向散列函数,对称加密,非对称加密,混合密码系统

    2024年01月24日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包