【计算机网络】HTTP协议(二)——超文本传输协议

目录

一、引言------回顾上文

二、解析报文

三、HTML超文本标记语言

[1、HTML 基础概念](#1、HTML 基础概念)

2、基本结构

3、常用标签

4、、语义化标签(HTML5新增)

5、属性与注释

6、示例代码

四、strtok分割函数

1、函数原型

2、核心特性

3、使用示例

4、注意事项

5、替代方案

6、常见问题

一、引言------回顾上文

  • HTTP请求方法:GET,POST
  • HTTP应答状态:100~500

二、解析报文

1、创建套接字,指定端口创建监听队列

2、接受连接,此时需要浏览器发起请求,客户端才会返回。

3、recv接收整个报文,获取整个资源的名称(strtok分割函数)

4、打开文件,选择存放的路径,

5、开始解析,获取文件大小

注:这里没有采用多线程,只采用短连接。多线程可以实现多个浏览器同时连接。

cpp 复制代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>//打开方式
char *get_filename(char buff[]){
    char *s=strtok(buff,"");//用空格分割,第一次分割为get
    while (s==NULL)
    {
        return NULL;
    }
    s=strtok(NULL,"");//第二次为要解析的数据
    return s;
}
int main(){
    //创建套接字,返回值:文件描述符,参数:收到,流式服务
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd==-1){
        exit(1);//退出
    }
    struct sockaddr_in saddr,caddr;//saddr代表服务器的,caddr代表客户端即浏览器
    memset(&saddr,0,sizeof(saddr));//先清空套接字地址,在进行填充
    saddr.sin_family =AF_INET;
    saddr.sin_port =htons(80);
    saddr.sin_addr.s_addr =inet_addr("127.0.0.1");
    //绑定ip和端口
    int res =bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
    if(res==-1){
        printf("bind err\n");//绑定失败打印错误信息
        exit(1);
    }
    //创建监听队列
    res =listen(sockfd,5);
    if(res==-1){
        exit(1);
    }
    while(1){//短链接
        //接收客户端连接
        int len=sizeof(caddr);
        int c=accept(sockfd,(struct sockaddr*)&caddr,&len);//如果客户端不连接则会阻塞
        if(c<0){
            continue;
        }
        printf("accept c=%d\n",c);
        //c就是描述符,通过描述符和客户端进行沟通
        char buff[1024]={0};
        int n=recv(c,buff,1023,0);//这时从c上接收数据,把数据存入buff中
        printf("buff=%s\n",buff);
        //给客户端回复数据
        char *filename=get_filename(buff);//解析数据
        if(filename==NULL){
            close(c);
            continue;
        }
        //设置存放位置
        char path[256]={"/home/stu/mycode/c2408/day19"};//存放位置
        if(strcmp(filename,"/")==0){
            strcat(path,"/index.html");//如果filename只有一个/,自定义设置名字
        }else{
            strcat(path,filename);//若有多个,则拼接
        }
        int fd=open(path,O_RDONLY);//打开方式,只读
        if(fd==-1){//如果打开失败回复404
            send(c,"404",3,0);
            close(c);
            continue;
        }
        //发送头部
        //获得文件大小:lseek   
        int size=lseek(fd,0,SEEK_END);//0=距离末尾多远,即0个字节。获取文件大小,文件偏移量移动到文件末尾
        lseek(fd,0,SEEK_SET);//复原文件偏移量到起始位置,否则下次读不到
        char head[256]="HTTP/1.1 200 ok\r\n";
        strcat(head,"Server:myhttp\r\n");
        sprintf(head+strlen(head),"Content=Length:%d\r\n",size);
        //数据部分和头部之间有一个空格请求,标识头部字段结束
        strcat(head,"\r\n");//空行
        //数据部分
        // strcat(head,"hello");
        send(c,head,strlen(head),0);
        printf("head:\n%s\n",head);
        //发送数据部分
        char data[1024]={0};//文件数据
        int num=0;//每次读取多少
        while(num=read(fd,data,1024)>0){//从fd读取,存储到data中,希望读1024
            //如个num>0,则读到数据
            send(c,data,num,0);//把data中的数据发送给浏览器,发送num个
        }
        close(fd);
        close(c);
    }  
}

三、HTML超文本标记语言

1、HTML 基础概念

HTML(HyperText Markup Language)是用于创建网页的标准标记语言。它通过标签(Tags)定义网页的结构和内容,例如文本、图像、链接等。浏览器解析HTML代码后渲染出可视化页面。

2、基本结构

一个标准的HTML文档包含以下核心部分:

html 复制代码
<!DOCTYPE html>
<html>//开始标签
<head>//头部标签
    <title>页面标题</title>
    <meta charset="UTF-8">
</head>
<body>//文件主体
    <!-- 页面内容 -->
</body>
</html>//末尾标签
  • <!DOCTYPE html> 声明文档类型为HTML5。
  • <html> 是根元素,包含整个页面内容。
  • <head> 存放元数据(如标题、字符集、CSS/JS链接)。
  • <body> 包含用户可见的内容。

3、常用标签

文本标签

  • <h1><h6>:标题(h1最大,h6最小)。
  • <p>:段落。
  • <a href="url">:超链接。
  • <strong><b>:加粗文本。
  • <em><i>:斜体文本。

多媒体标签

  • <img src="image.jpg" alt="描述">:插入图片。
  • <audio><video>:嵌入音视频。
  • <iframe src="url">:嵌入其他网页。

列表与表格

  • <ul>(无序列表)和<ol>(有序列表)配合<li>使用。
  • <table> 定义表格,配合<tr>(行)、<td>(单元格)使用。

表单标签

html 复制代码
<form action="/submit" method="post">
    <input type="text" name="username" placeholder="输入用户名">
    <input type="password" name="pwd">
    <button type="submit">提交</button>
</form>
  • <input> 支持多种类型(text、password、checkbox等)。
  • <textarea> 多行文本输入。
  • <select> 下拉选择框。

4、、语义化标签(HTML5新增)

  • <header>:页眉或内容头部。
  • <nav>:导航栏。
  • <section>:文档中的独立区块。
  • <article>:独立内容(如博客文章)。
  • <footer>:页脚。

5、属性与注释

  • 属性 :为标签提供额外信息,如<a href="https://example.com" target="_blank">中的target="_blank"表示在新窗口打开链接。
  • 注释<!-- 注释内容 -->,不会在页面显示。

6、示例代码

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <title>示例页面</title>
</head>
<body>
    <h1>欢迎</h1>
    <p>这是一个段落。<a href="https://example.com">示例链接</a></p>
    <img src="example.jpg" width="200" alt="示例图片">
</body>
</html>

四、strtok分割函数

strtok 是 C 标准库(<string.h>)提供的字符串分割函数,用于按指定分隔符将字符串拆分为多个子串(token)。

1、函数原型

c 复制代码
char *strtok(char *str, const char *delimiters);
  • str : 待分割的字符串(首次调用时传入,后续调用需传入 NULL)。
  • delimiters: 分隔符集合(每个字符均视为独立分隔符)。
  • 返回值 : 返回下一个子串的指针;若无更多子串则返回 NUL

2、核心特性

  1. 修改原字符串
    strtok 会在分隔符位置插入 '\0',直接修改原字符串。若需保留原字符串,应先拷贝再分割。

  2. 状态依赖

    首次调用需传入目标字符串,后续调用需传入 NULL(函数内部静态指针记录剩余部分)。


3、使用示例

c 复制代码
#include <stdio.h>
#include <string.h>

int main() {
    char str[] = "apple,banana,cherry";
    const char *delim = ",";
    char *token = strtok(str, delim);

    while (token != NULL) {
        printf("Token: %s\n", token);
        token = strtok(NULL, delim);
    }
    return 0;
}

输出:

cpp 复制代码
Token: apple
Token: banana
Token: cherry

4、注意事项

  1. 线程不安全

    静态指针导致 strtok 不可重入。多线程环境下应使用 strtok_r(POSIX 标准)或 strtok_s(C11 标准)。

  2. 连续分隔符处理

    连续的分隔符会被视为单个分隔符。例如 "a,,b""," 分割得到 "a""b"

  3. 空字符串

    若字符串仅含分隔符(如 ","),首次调用返回 NULL


5、替代方案

  • strtok_r(可重入版本)

    c 复制代码
    char *strtok_r(char *str, const char *delim, char **saveptr);

    通过 saveptr 参数保存状态,避免静态变量。

  • strsep(BSD 扩展)

    c 复制代码
    char *strsep(char **stringp, const char *delim);

    更高效但会修改输入指针,适合高频分割场景。


6、常见问题

  1. 分割后原字符串丢失

    c 复制代码
    char *str = strdup("a,b,c");  // 必须拷贝原字符串
    char *token = strtok(str, ",");
    // 使用后释放拷贝的字符串
    free(str);
  2. 混合分隔符

    c 复制代码
    char str[] = "apple.banana,cherry";
    char *token = strtok(str, ".,");  // 同时使用 '.' 和 ','
相关推荐
Daniel_Coder4 小时前
iOS Widget 开发-8:手动刷新 Widget:WidgetCenter 与刷新控制实践
ios·swift·widget·1024程序员节·widgetcenter
清风徐来Groot4 小时前
WPF绘制界面常用功能
1024程序员节
MeowKnight9584 小时前
【C】函数指针
c语言·1024程序员节
雾江流4 小时前
元萝卜 1.0.27| 免Root,XP模块框架,支持应用多开分身,一键微信平板模式
软件工程·1024程序员节
禾仔仔4 小时前
USB2.0枚举流程(以鼠标为例)——从零开始学习USB2.0协议(四)
嵌入式硬件·mcu·计算机外设·1024程序员节
TeleostNaCl4 小时前
一种使用 PowerToys 的键盘管理器工具编辑惠普暗影精灵11 的 OMEN 自定义按键的方法
windows·经验分享·计算机外设·1024程序员节
码力引擎4 小时前
【零基础学MySQL】第一章:MySQL介绍与安装
数据库·mysql·1024程序员节
体育分享_大眼4 小时前
体育数据传输:HTTP API与WebSocket的核心差异
1024程序员节
Python大数据分析@4 小时前
Python哪个Excel库最好用?
1024程序员节