【Linux 网络编程2】应用层协议--http;序列化和反序列化,get和post请求传参的区别,cookie和sesion,编写一个简单的http

news2024/11/28 10:54:46

目录

1.序列化和反序列化

2.HTTP协议

 3.编写一个简单的http

 3.2.简单的http的使用

 3.3.get和post请求传参的区别

4.http的状态码分类

5.cookie和sesion


1.序列化和反序列化

1.1.序列化和反序列化的优势

  1. 序列化将结构体转化为长字符串,便于传输;
  2. 反序列化在应用层将长字符串转化会结构体,序列化和反序列化都由应用层来处理,传输层只考虑传输的问题;实现了应用层和传输层的解耦

1.2.序列化和反序列化需要那些要求

  1. 双方都要知道结构体的成员的类型;
  2. 双方都要知道序列化和反序列化的格式;

双方都要知道的条件不就是一种协议吗

2.HTTP协议

HTTP(超文本传输协议)是一个应用层协议,超文本:含有指向其它文本文件链接的文本

  • http没有建立连接和关闭连接,有程序员处理

http协议通常以3到4部分组成:

2.1.URL就是网址

 3.编写一个简单的http

3.1查看http的请求

套接字的封装:socket.hpp

#pragma once
#include<iostream>
#include<cstdlib>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<arpa/inet.h>

namespace ns_socket{
    class sock{
    public:
        static int Socket()
        {
            int sock=socket(AF_INET,SOCK_STREAM,0);
            if(sock<0)
            {
                std::cerr<<"socket"<<std::endl;
                exit(1);
            }
            return sock;
        }
        static void Bind(int sock,int port)
        {
            struct sockaddr_in local;
            local.sin_family=AF_INET;
            local.sin_addr.s_addr=INADDR_ANY;
            local.sin_port=htons(port);
            if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)
            {
                std::cerr<<"bind"<<std::endl;
                exit(2);
            }
        }
        static void Listen(int sock)
        {
            if(listen(sock,5)<0)
            {
                std::cerr<<"listen"<<std::endl;
                exit(3);
            }
        }
        static int Accept(int sock) 
        {
            struct sockaddr_in tmp;
            socklen_t tlen=sizeof(tmp);
            int new_sock=accept(sock,(struct sockaddr*)&tmp,&tlen);
            if(new_sock<0)
            {
                std::cerr<<"accept"<<std::endl;
                exit(4);
            }
            return new_sock;  
        }
        static void Connect(int sock,char* server_ip,char* server_port)
        {
            struct sockaddr_in local;
            local.sin_family=AF_INET;
            local.sin_addr.s_addr=inet_addr(server_ip);
            local.sin_port=htons(atoi(server_port));
            if(connect(sock,(struct sockaddr*)&local,sizeof(local))<0)
            {
                std::cerr<<"connect"<<std::endl;
                exit(5);
            }
            else
            {
                std::cout<<"connet success"<<std::endl;
            }
        }
    };
}

服务器端获取http的请求并打印打出来

#include "socket.hpp"
#include <string>
#include <pthread.h>
#include <unistd.h>

using namespace ns_socket;
using namespace std;

#define CAPACITY 1024 * 10

void *HandlerRequest(void *args)
{
    pthread_detach(pthread_self());//线程分离
    int new_sock = *((int *)args);
    //获取http请求
    char buffer[CAPACITY]={0};
    ssize_t s=recv(new_sock,buffer,sizeof(buffer)-1,0);
    if(s>0)
    {
        buffer[s]=0;
        cout<<buffer<<endl;
    }
    //关闭连接
    close(new_sock);
}

建立网络通信 

int main()
{
    int sock = sock::Socket();
    sock::Bind(sock, 8080);
    sock::Listen(sock);
    while (1)
    {
        int new_sock = sock::Accept(sock);
        cout << "get a new link" << endl;
        pthread_t tid;
        pthread_create(&tid, 0, HandlerRequest, (void *)&new_sock);
    }
    return 0;
}

 执行结果:

 3.2.简单的http的使用

前端代码

<!DOCTYPE html>

<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <h3>你好吗!</h3>
    </body>
</html>

其它的代码和上面的一样,只有这个线程执行的函数不同

#include "socket.hpp"

#include <string>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fstream>

using namespace ns_socket;
using namespace std;

#define CAPACITY 1024 * 10
#define WWWROOT "./wwwroot/"
#define HOME_PAGE "index.html"

void *HandlerRequest(void *args)
{
    pthread_detach(pthread_self());
    int new_sock = *((int *)args);

    // 资源路径
    std::string file_path = WWWROOT;
    file_path += HOME_PAGE;
    //打开资源文件
    ifstream in(file_path.c_str());
    if (in.is_open())
    {
        // 获取文件属性
        struct stat page_stat;
        stat(file_path.c_str(), &page_stat);

        //编写http的响应
        std::string http_response;
        http_response += "http/1.0 200 ok\n";;//状态行
        http_response += "Content-Type: text/html\n";//资源是什么类型,查content-type对照表
        //资源的长度,字节为单位
        http_response += "Content-Longth: ";
        http_response += std::to_string(page_stat.st_size);
        http_response += "\n";
        http_response += "\n"; // 空行

        // http的有效载荷,正文
        std::string content;
        std::string line;
        while (std::getline(in, line))
        {
            content += line;
        }
        http_response += content;
        //把响应发给对端 
        send(new_sock, http_response.c_str(), http_response.size(), 0);
    }
    close(new_sock);
}

执行的结果:

 

 3.3.get和post请求传参的区别

3.3.2.<form action="/a/b/handler_from" method="GET">,使用GET传参数;

<!DOCTYPE html>

<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <h5>hello 我是首页!</h5>

        <h5>hello 我是表单!</h5>

        <form action="/a/b/handler_from" method="GET">
            姓名: <input type="text" name="name"><br/>
            密码: <input type="password" name="passwd"><br/>
            <input type="submit" value="登陆">
        </form>
    </body>
</html>

 使用GET传参数,参数是通过URL传参的;

 3.3.2.<form action="/a/b/handler_from" method="POST">,使用POST传参数;

<!DOCTYPE html>

<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <h5>hello 我是首页!</h5>

        <h5>hello 我是表单!</h5>

        <form action="/a/b/handler_from" method="POST">
            姓名: <input type="text" name="name"><br/>
            密码: <input type="password" name="passwd"><br/>
            <input type="submit" value="登陆">
        </form>
    </body>
</html>

  使用POST传参数,参数是通过正文传参的;

 3.3.3.get和post的区别

  1. get方法通常是做获取网页的,但是也可以用做传参,通过与URL拼接的方式参数传输;post通常用于参数传递,通过http的请求的正文传递给server端;
  2. get做为参数传参会回显在浏览器的搜索栏,没有通过正文部分传递参数的post的私密性更强,且get使用URL传递参数是有大小现在1024kb,所以在信息不敏感且数量较少的情况下使用get传递参数比较适合;

4.http的状态码分类

数字类型含义类型解释
1XXInformation(信息型状态码)接受的请求正在处理(不常见,处理的请求通常不会很长)
2XXSuccess(成功状态码)类似200 表示请求被处理成功
3XXRedirection(重定向状态码)访问某一个服务器,会响应到其他网址;跳转到其他网址
4XXClinet Error类似404 Not Found ,服务器处理不了请求
5XXServer Error服务器处理请求失败

4.1.重定向如何实现

  • location报文配合301永久重定向或者302临时重定向使用
void *HandlerRequest(void *args)
{
    pthread_detach(pthread_self());
    int new_sock = *((int *)args);

    std::string response;
    response+="http/1.0 301 Permanently moved\n";
    response+="Location: https://www.baidu.com/\n";//location报文配合301永久重定向或者302临时重定向使用
    response+="\n";

    send(new_sock,response.c_str(),response.size(),0);

    close(new_sock);
}

5.cookie和sesion

5.1.为什么需要cookie

当我们登录CSDN后,访问任一一篇文章都是一个另外新的链接http协议是一个无状态的协议(不会认识用户),为什么不需要我们再输入一次密码,来验证是用户;

cookie中保存用户的私密信息,如果每次都需要我们输入账号密码会让客户端的体验变差

5.2.cookie的思想和自己写一个cookie

  1. 保证了用户的体验
  2. 但是cookie保存在浏览器的文件或者内存中,用户能找到那么黑客也可以找到,客户端的问题没法让服务器端解决,只能靠用户不访问恶意链接

  

 5.2.1.自己写一个简单cookie测试

  •  Set-Cookie添加cookie
  • 其他代码和上面一样
void *HandlerRequest(void *args)
{
    pthread_detach(pthread_self());
    int new_sock = *((int *)args);
    
    char client_requist[1024*10]={0};

    recv(new_sock,client_requist,sizeof(client_requist)-1,0);
    std::cout<<client_requist<<std::endl;
    std::string response;

    response+="http/1.0 200 OK\n";
    //Set-Cookie添加cookie
    response+="Set-Cookie: id=123456\n";
    response+="Set-Cookie: password=654321\n";
    response+="\n";//空行
    send(new_sock,response.c_str(),response.size(),0);

    close(new_sock);
}

 5.3.sesion(英文会话的意思)

因为如果cookie直接保存用户的账号密码,被盗取就非常危险;

  • sesion就是把这些私密信息保存在对端服务器(比如私密信息保存在CSDN的服务器,大型公司通常不容易被入侵),然后返回一个唯一的值保存到浏览器cookie中,即使被盗取也是只有数据被泄漏,账号密码等私密信息没有被泄漏

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/402305.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MyBatis源码用了哪些设计模式?

MyBatis源码用了哪些设计模式&#xff1f;前言一、创建型模式工厂模式单例模式建造者模式二、结构型模式适配器模式代理模式组合模式装饰器模式三、行为型模式模板模式策略模式迭代器模式总结前言 在 MyBatis 的两万多行的框架源码中&#xff0c;使用了大量的设计模式对工程架…

Oracle OCP 19c 考试(1Z0-083)中关于Oracle不完全恢复的考点(文末附录像)

欢迎试看博主的专著《MySQL 8.0运维与优化》 下面是Oracle 19c OCP考试&#xff08;1Z0-083&#xff09;中关于Oracle不完全恢复的题目: A database is configured in ARCHIVELOG mode A full RMAN backup exists but no control file backup to trace has been taken A media…

Spatial-Temporal Graph ODE Networks for Traffic Flow Forecasting

Spatial-Temporal Graph ODE Networks for Traffic Flow Forecasting 摘要 交通流量的复杂性和长范围时空相关性是难点 经典现存的工作&#xff1a; 1.利用浅图神经网络&#xff08;shallow graph convolution networks&#xff09;和 时间提取模块去分别建模空间和时间依赖…

【Python3安装部署的保姆级教程】

如何在Windows 10上安装Python Python是一种越来越受欢迎的编程语言,无论是对于初学者还是有经验的开发者。Python灵活多用,擅长脚本、自动化、数据分析、机器学习和后端开发。在本教程中,你将学习如何使用Windows的Python安装程序在Windows 10上安装Python。 第一步 — 下…

Python3-错误和异常

Python3 错误和异常 作为 Python 初学者&#xff0c;在刚学习 Python 编程时&#xff0c;经常会看到一些报错信息&#xff0c;在前面我们没有提及&#xff0c;这章节我们会专门介绍。 Python 有两种错误很容易辨认&#xff1a;语法错误和异常。 Python assert&#xff08;断…

进程间通信IPC

进程间通信IPC (InterProcess Communication) 一、进程间通信的概念 每个进程各自有不同的用户地址空间&#xff0c;任何一个进程的全局变量在另一个进程中都看不到&#xff0c;所以进程之间要交换数据必须通过内核&#xff0c;在内核中开辟一块缓冲区&#xff0c;进程1把数据…

MySQL事务详解与隔离级别的实现

文章目录一、四个特性二、存在问题三、隔离级别四、实现原理0、SQL语句执行流程1&#xff09;buffer pool2&#xff09;执行流程1、日志1&#xff09;binlog2&#xff09;redolog3&#xff09;对比4&#xff09;undolog2、MVCC原理1&#xff09;隐式字段2&#xff09;undo log版…

气泡式水位计的安装方法详解

气泡水位计的安装实际上就是气管的安装&#xff0c;气管的安装是否正确将直接影响到仪器测量数据的结果&#xff0c;气泡水位计它由活塞泵产生的压缩空气流经测量管和气泡室&#xff0c;进入被测的水体中&#xff0c;测量管中的静压力与气泡室上的水位高度成正比。那么接下来就…

蓝桥杯集训·每日一题Week1

前缀和&#xff08;Monday&#xff09; AcWing 3956. 截断数组&#xff08;每日一题&#xff09; 思路&#xff1a; 首先可以预处理出前缀和。判断数组长度如果小于 333 或者前 nnn 项不是 333 的倍数&#xff0c;则可以直接输出 000。 否则就枚举所有 s[i]s[n]3s[i] \cfrac…

kali双网卡

先单独开启一个网卡&#xff0c;配置/etc/network/interfaces 修改为如下配置 This file describes the network interfaces available on your system and how to activate them. For more information, see interfaces(5). source /etc/network/interfaces.d/* The loopb…

JVM系列——Java与线程,介绍线程原理和操作系统的关系

并发不一定要依赖多线程(如PHP中很常见的多进程并发)。 但是在Java里面谈论并发&#xff0c;基本上都与线程脱不开关系。因此我们讲一下从Java线程在虚拟机中的实现。 线程的实现 线程是比进程更轻量级的调度执行单位。 线程的引入&#xff0c;可以把一个进程的资源分配和执行调…

【深度强化学习】(3) Policy Gradients 模型解析,附Pytorch完整代码

大家好&#xff0c;今天和各位分享一下基于策略的深度强化学习方法&#xff0c;策略梯度法是对策略进行建模&#xff0c;然后通过梯度上升更新策略网络的参数。我们使用了 OpenAI 的 gym 库&#xff0c;基于策略梯度法完成了一个小游戏。完整代码可以从我的 GitHub 中获得&…

原型模式(设计模式详解)

原型模式 描述 原型模式&#xff08;Prototype Pattern&#xff09;是一种创建型设计模式&#xff0c;它允许通过复制现有对象来创建新对象&#xff0c;而无需从头开始编写代码。 在原型模式中&#xff0c;一个原型对象作为模板&#xff0c;新的对象通过克隆这个原型对象而创…

MySQL OCP888题解048-letter N in slow query log(慢查询日志里的字母N)

文章目录1、原题1.1、英文原题1.2、中文翻译1.3、答案2、题目解析2.1、题干解析2.2、选项解析3、知识点3.1、知识点1&#xff1a;mysqldumpslow - 总结缓慢的查询日志文件4、实验4.1、实验14.1.1、实验目的4.1.2、实验前准备4.1.3、实验步骤4.1.4、实验结论5、总结1、原题 1.1…

dva01-初识

背景 React 本身只是一个 DOM 的抽象层&#xff0c;使用组件构建虚拟 DOM。如果开发大应用&#xff0c;还需要解决一个问题。 通信&#xff1a;React 只提供了一种传参手段&#xff0c;后续数据变化非常麻烦&#xff0c;无法适用于大应用。数据流&#xff1a;每次要更新数据&…

ACE C++网络通信框架深入解析ACE_Message_Block消息类

前言 我所见到最好消息包的接口设计莫过于ACE_Message_Block了。 为什么这样说呢&#xff1f; 对于它的API说明&#xff0c;我最初仅想在它的基础上提供注释说明&#xff0c;而不想多言其它&#xff0c;因为无需多言其他。 不过&#xff0c;后来还是补充两个图&#xff0c;以…

后台搭建常用方式及常用的插件

利用脚手架创建项目 create-vite 是一个快速生成主流框架基础模板的工具,安装后启动预设创建项目 使用NPM&#xff1a; npm create vitelatest 使用Yarn: yarn create vite 使用PNPM: pnpm create vite 开始 | Vite 官方中文文档 create-vue&#xff0c;是 Vue 官方的项目脚…

Flume工作原理 安装配置

目录 简介 主要功能 日志收集 数据处理 工作原理 Flume架构 安装 拷贝压缩包 解压 改名 修改配置文件 安装nc&#xff08;netcat&#xff09; 安装telnet协议 应用 应用一&#xff1a;实时监听 新建netcat-logger.conf文件 开启端口监听方式一 访问主机 开启…

flume安装与配置

目录 flume描述 flume用途 flume基本组件 配置flume 搭建环境&#xff1a; 解压flume安装包将其放入到opt/soft目录 在/opt/soft目录下将apache-flume-1.9.0-bin.tar.gz 改名为flume190 到/opt/soft/flume190/conf目录中将临时配置文件flume-env.sh.template拷贝为配置文…

香港酒店模拟分析项目报告--使用tableau、python、matlab

转载请标记本文出处 软件&#xff1a;tableau、pycharm、关系型数据库&#xff1a;MySQL 数据大量分析考虑电脑性能的情况。 文章目录前言一、爬虫是什么&#xff1f;二、使用tableau数据可视化1.引入数据1.1 制作直方图-各地区酒店数量条形图1.2 各地区酒店均价1.3 价格等级堆…