学习记录——day33 HTTP

news2024/11/25 16:52:52

目录

一、HTTP相关概念

二、客服端请求

1、请求首部

2、 响应首部

三、线程实现HTTP并发服务器


一、HTTP相关概念

1、HTTP,全称Hyper Text Transfer Protocol,用于万维网(world wide web)进行超文本学习的传输协议

2、HTTP属于应用层,对应的传输层是TCP

3、http是基于BS模型,即浏览器服务器模型,主要完成的是客户端请求端和服务器相应端

4、Hypertext Markup Language 超文本标记语言,属于标签式语言,能够被浏览器所识别

二、客服端请求

1、请求首部

1)任何一个http请求都由三部分组成:请求首部、请求主体、请求数据

2)对于客户端请求协议包而言,一般没有请求数据,具体格式如下

 

2、 响应首部

1)响应首部也是由三部分组成,分别是响应头、响应主体、响应数据

2)对于响应首部而言,必须由响应数据

3)http的响应代号:1XX (信息状态错误) 2XX(成功) 、3XX(重定向状态码)、4XX(客户端错误)、5XX(服务器出错) 

三、线程实现HTTP并发服务器

有BUG

#include <myhead.h>
#define SER_PORT 80
#define SER_IP "192.168.0.106"

void do_notfound(int newfd);
void do_response(int newsfd, const char *url);
int send_head(int newfd, int file_size);
void send_html(int newfd, int fd);
void do_server_error(int newfd);
int get_one_line(int newfd, char msg[]);

// 线程用信息初传输结构体
struct Info
{
    struct sockaddr_in cin;
    int newsfd;
};

// 线程处理函数
void *deal_cli_msg(void *arg)
{
    int newsfd = ((struct Info *)arg)->newsfd;
    struct sockaddr_in cin = ((struct Info *)arg)->cin;
    while (1)
    {
        // 5、数据收发
        char buf[128] = "";

        // 获取请求头部
        get_one_line(newsfd, buf);

        // 获取请求方法
        char mathod[5] = "";              // 存储请求方法
        strcpy(mathod, strtok(buf, " ")); // 分割字符串并将分割下来的第一个字符串存入mathod
        char url[50] = "";
        char n_url[256] = "";
        strcpy(url, strtok(NULL, " ")); // 在上一次分割的基础上,将第二个字符串存入url

        if (strcmp(mathod, "GET") == 0)
        {
            // 完成相应工作
            // 重组url
            snprintf(n_url, sizeof(n_url), "./htmls%s", url);

            // 判断要访问的文件是否存在
            if (access(n_url, F_OK) == -1)
            {
                // 返回错误信息
                do_notfound(newsfd);
                break;
            }
            else
            {
                // 响应
                do_response(newsfd, n_url);
            }
        }
        else
        {
            // 非法请求
            // do_illigal(newsfd);
        }
    }
    pthread_exit(EXIT_SUCCESS);
}

int get_one_line(int newfd, char msg[])
{
    char buf = '\0';
    int i = 0;

    while (1)
    {
        int res = recv(newfd, &buf, 1, 0);
        if (0 == res)
        {
            break;
        }
        else if (1 == res)
        {
            if (buf == '\n')
            {
                break;
            }
            else
            {
                msg[i] = buf;
                i++;
            }
        }
        else
        {
            perror("recv error");
            return -1;
        }
    }

    msg[i] = '\0';
}

// 响应函数
void do_response(int newsfd, const char *url)
{
    // 1、以只读的形式打开文件
    int fd = open(url, O_RDONLY);
    if (-1 == fd)
    {
        /* 服务器内部错误 */
        do_server_error(newsfd);
        return;
    }

    // 2、获取文件大的长度
    int file_size = lseek(fd, 0, SEEK_END);

    // 3、封装响应头部发送给客服端
    int res = send_head(newsfd, file_size);
    if (0 == res)
    {
        return;
    }

    // 4、发送html文档给客服端
    lseek(fd, 0, SEEK_SET);
    // send_html(newfd,fd);

    printf("响应成功\n");
    close(fd); // 关闭文件
}

// 头部发送函数
int send_head(int newfd, int file_size)
{
    char *head = "HTTP/1.1 200 OK\r\nContent-Type:text/html\r\n";

    char n_head[512] = "";
    snprintf(n_head, sizeof(n_head), "%sContent-Length:%d\r\n\r\n", head, file_size);

    printf("n_head = %s\n", n_head);

    // 将头部发送个客服端
    int res = send(newfd, n_head, strlen(n_head), 0);

    return res;
}

// 发送文件函数
void send_html(int newfd, int fd)
{
    char buf[128] = "";
    while (1)
    {
        /* 从文件中读取数据 */
        int res = read(fd, buf, sizeof(buf));
        if (-1 == res)
        {
            /* 服务器内部出错 */
            do_server_error(newfd);
            return;
        }
        else if (0 == res)
        {
            /* 读取结束 */
            break;
        }

        // 将数据发送给客服端
        send(newfd, buf, res, 0);
    }
}

// 服务器内部出错
void do_server_error(int newfd)
{
    char *msg = "HTTP/1.1 502 SERVER_ERROR\r\nContrnt-Type-text/html\r\n";

    // 向客服端发送错误信息
    send(newfd, msg, strlen(msg), 0);

    // 定义要发送的数据
    char *msg_html = "<!DOCTYPE html>\n\
<html lang=\" en \">\n\
<head>\n\
    <meta charset=\" UTF -\
                     8 \">\n\
    <meta name=\" viewport \" content=\" width = device - width,\
         initial - scale = 1.0 \">\n\
    <title>502 SERVER_ERROR</title>\n\
</head>\n\
<body>\n\
    <h1>服务器内部出错</h1>\n\
    <p>文件描述符打开出错</p>\n\
</body>\n\
</html>";

    send(newfd, msg_html, strlen(msg_html), 0);
}

// 对象访问界面不存在
void do_notfound(int newfd)
{
    char *msg = "";

    // 向客服端发送错误信息
    send(newfd, msg, strlen(msg), 0);

    // 定义要发送的数据
    char *msg_html = "HTTP/1.1 404 NOT_FOUND\r\nContrnt-Type-text/html\r\n\
                     < !DOCTYPE html >\n<html lang = \" en \">\n<head>\n < meta charset = \" UTF -8 \">\n\
    <meta name=\" viewport \" content=\" width = device - width,initial - scale = 1.0 \">\n\
    <title>502 SERVER_ERROR</title>\n\
</head>\n\
<body>\n\
    <h1>404 NOT_FOUND</h1>\n\
    <p>e界面不存在</p>\n\
</body>\n\
</html>";
}

int main(int argc, char const *argv[])
{
    // 1、创建套接字
    int sfd = socket(AF_INET, SOCK_STREAM, 0);
    // 参数1:ipv4的网络通信
    // 参数2:TCP通信方式
    // 参数3:默认使用一个协议

    if (sfd == -1)
    {
        perror("socket error");
        return -1;
    }

    printf("socket success, sfd = %d\n", sfd); // 3

    // 2、为套接字绑定ip地址和端口号
    // 2.1 填充地址信息结构体
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;                // 通信域
    sin.sin_port = htons(SER_PORT);          // 端口号
    sin.sin_addr.s_addr = inet_addr(SER_IP); // ip地址

    // 2.2 绑定
    if (bind(sfd, (struct sockaddr *)&sin, sizeof(sin)) == -1)
    {
        perror("bind error");
        return -1;
    }
    printf("bind success\n");

    // 3、将套接字设置为被动监听状态,用于接收
    if (listen(sfd, 128) == -1)
    {
        perror("listen error");
        return -1;
    }
    printf("listen success\n");

    // 4、阻塞等待客户端的连接请求
    // 4.1 定义n变量用于e接收客服端的信息
    struct sockaddr_in cin;
    socklen_t addrlen = sizeof(cin);

    while (1) // 循环服务器
    {
        // 4.2 接收连接
        int newsfd = accept(sfd, (struct sockaddr *)&cin, &addrlen);
        if (newsfd == -1)
        {
            perror("accept error");
            return -1;
        }
        printf("[%s:%d]:accept on\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port));

        struct Info cli_info = {cin,newsfd};

        // 创建分支线程用于处理客服端请求
        pthread_t tid = -1;
        if (pthread_create(&tid, NULL, deal_cli_msg, &cli_info) != 0)
        {
            /* 出错 */
            printf("tid create error");
            return -1;
        }

        //将线程设置为n分离态
        pthread_detach(tid);
    }

    close(sfd);
    return 0;
}

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

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

相关文章

如何使用 Java 记录简化 Spring Data 中的数据实体

Java 开发人员一直依赖 Spring Data 来实现高效的数据访问。但是&#xff0c;随着 Java Records 的引入&#xff0c;数据实体的管理方式发生了重大变化。 在本文中&#xff0c;我们将讨论 Java Records 在 Spring Data 应用程序中的集成。我们将探讨使用 Java 记录创建健壮的数…

CGAL 线性插值(自然邻近坐标)

文章目录 一、简介二、实现代码三、实现效果一、简介 自然邻近坐标插值(Natural Neighbor Interpolation)是一种基于Voronoi图的插值方法。它被广泛应用于地理信息系统(GIS)、计算几何以及科学计算领域。该方法的核心思想是利用数据点的Voronoi单元来确定插值点的权重,从而…

基于java的酒店管理系统设计与实现

系统分析与设计 需求分析 1.系统概要 根据餐饮系统的流程&#xff0c;完成从用户登录到开台点菜&#xff0c;到结账收银&#xff0c;到统计一条线的信息化管理&#xff0c;因此整个餐饮管理信息系统的研发内容就是开发一整套餐饮管理信息系统&#xff0c;实现餐饮业务的计算…

【三维重建】2D Gaussian Splatting:几何准确的2D辐射场(更新中)

标题&#xff1a;2D Gaussian Splatting for Geometrically Accurate Radiance Fields 项目地址&#xff1a;https://github.com/hbb1/2d-gaussian-splatting 文章目录 功能输入输出 一、摘要二、引言深入分析解读 三、相关工作3.1新视角合成3.2 3D重建3.3 可微分基于点的图形…

Manim动画:相机的移动(MovingCameraScene)

1.相机的移动(MovingCameraScene) MovingCameraScene 是 Manim 中的一个类&#xff0c;用于创建可以移动的相机场景。这个类继承自 Scene&#xff0c;并提供了关于相机移动的额外功能。 MovingCameraScene(camera_class<class manim.camera.moving_camera.MovingCamera>…

搭建ELK日志采集与分析系统

SpringCloud微服务实战——企业级开发框架 &#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您…

5.Linux_Shell编程

概述 什么是shell脚本&#xff1a; Shell脚本是利用shell的功能所写的一个程序。这个程序是使用纯文本文件&#xff08;后缀为.sh&#xff09;&#xff0c;将一些shell的语法与命令&#xff08;含外部命令&#xff09;写在里面&#xff0c;搭配正则表达式、管道命令与数据流重…

【QT代码控制Linux开发板】QT控制嵌入式Linux开发板运行shell脚本

一. 前言 最近遇到了一个很冲突的问题&#xff0c;我想让比如qt代码控制传感器读取的数值大于某个阈值时控制板子的灯亮进行报警。 但是当我在Linux开发板上./运行交叉编译后的qt文件时&#xff0c;想运行开发板的其他shell语句必须先退出qt代码的执行&#xff0c;当然开发板…

ios白苹果修复办法有哪些?

在这个数字化时代&#xff0c;iPhone作为智能手机的佼佼者&#xff0c;早已融入了我们生活的方方面面。然而&#xff0c;当那熟悉的开机画面——“白苹果”意外地成为了你的日常&#xff0c;无疑让人头疼不已。别担心&#xff0c;今天我们就来聊聊iOS白苹果现象的成因及几种有效…

Element-ui table进阶使用

最近项目有多个报表开发的需求&#xff0c;我采用的是凤翎前端组件框架&#xff08;基于element-ui开发&#xff09;&#xff0c;大伙可以直接参考element-ui组件库文档&#xff0c;把标签中的fks替换为el即可。下面我会按顺序一一展开细说这些需求&#xff1a; 1、有多级表头…

Java语言程序设计基础篇_编程练习题***16.31(游戏:四子连)

目录 题目&#xff1a;***16.31&#xff08;游戏&#xff1a;四子连&#xff09; 习题思路 代码示例 结果展示 题目&#xff1a;***16.31&#xff08;游戏&#xff1a;四子连&#xff09; 编程练习题8.20让两个玩家在控制台上可以玩四子连的游戏。为这个程序重写一个GUI版本…

Open3D mesh 模型锐化

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 输入参数 输出参数 2.2完整代码 三、实现效果 3.1原始mesh 3.2处理后mesh 3.3数据显示 Open3D点云算法汇总及实战案例汇总的目录地址&#xff1a; Open3D点云算法与点云深度学习案例汇总…

反射异常捕获 | InvocationTargetException 要用e.getCause()打印才能看到具体异常

背景&#xff1a;线上某段和反射相关的代码报错了&#xff0c;但是异常信息打印只看到了 InvocationTargetException&#xff0c;没打印具体的异常。就像这样&#xff1a;java.lang.reflect.InvocationTargetException: null 查阅资料后发现要用e.getCause()才能打印具体异常&a…

[数据集][目标检测]航拍屋顶检测数据集VOC+YOLO格式458张3类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;458 标注数量(xml文件个数)&#xff1a;458 标注数量(txt文件个数)&#xff1a;458 标注类别…

深度剖析数字媒体产业链的无限潜力与创新生态

在当今信息爆炸的时代&#xff0c;数字媒体产业链正以势不可挡的姿态展现出其令人瞩目的无限潜力与创新生态。 数字媒体的发展潜力简直无可限量。从在线视频的爆发式增长&#xff0c;到虚拟现实和增强现实技术带来的沉浸式体验&#xff0c;再到社交媒体平台上丰富多彩的内容创…

抽象类与抽象函数+接口

抽象类与抽象函数 什么是抽象方法 抽象方法是没有实现代码的虚方法 抽象方法使用abstract修饰符进行声明&#xff0c;只能在同样声明了abstract的类中使用。 继承了抽象类的子类必须实现抽象类的所有抽象方法。 什么是抽象类 用abstract修饰过的类是抽象类 抽象类无法被…

《机器学习》 决策树 ID3算法

一、什么是决策树&#xff1f; 1、概念 决策树是机器学习中一种常见的分类和回归算法。它基于树状结构的模型&#xff0c;通过对数据进行逐步划分&#xff0c;最终生成一棵决策树来进行预测或分类任务。 在决策树中&#xff0c;每个节点代表一个特征或属性&#xff0c;每个分支…

数据库:数据更新和视图

1 实验目的 &#xff08;1&#xff09;掌握SQL语言的数据更新功能&#xff1a; update 语句用于对表进行更新 delete 语句用于对表进行删除 insert 语句用于对表进行插入 &#xff08;2&#xff09;掌握对视图的操作&#xff1a; 视图的定义 视图的更新 基于视图的查询 …

總結熱力學_4(完了)

參考: 陈曦<<热力学讲义>>http://ithatron.phys.tsinghua.edu.cn/downloads/thermodynamics.pdf 7 最大功定理 考虑一个与外界隔绝的由几个彼此不处于热平衡、但相互绝热的物体组成的系统。另外还需要一个重物,它不参与热力学过程,但是可以以重力势能的 方式存…

js vscode 关于对象数组的一个bug

数据结构&#xff1a; let address [{label: "北京市",children: []},{label: "天津市",children: []},{label: "上海市",children: []},{label: "重庆市",children: []},{label: "河北省",children: [{label: "石家…