Linux服务器开发——HTTP协议相关概念和web服务器实现伪代码

    技术2025-12-27  14

    Linux服务器开发——HTTP协议相关概念和web服务器实现流程

    1. HTTP的特点2. HTTP协议的结构1.1 请求报文(Request) - 浏览器给服务器发1.2 HTTP 中, POST 与 GET 的区别1.3 响应报文(Response) - 服务器给浏览器发 3. web服务器端伪代码

    Http协议是一种广泛流行的网络应用层协议。设计HTTP最初的目的是为了提供发布和接收HTML页面的方法。用于客户端和服务器端通信的通信的规则的制定(所谓协议就是约定的规则,好比人与人之间的交流没有约定的规则是无法交流的).只要是遵守Http协议的浏览器,服务器之间就可以进行通信。

    1. HTTP的特点

    支持客户端/服务器模式简单快速灵活无连接,所谓无连接是指默认http协议限制每一次连接只处理一个请求。服务器处理完客户端的请求,并受到客户端的应答后即断开连接。无状态,是指Http协议对事务处理没有记忆能力,服务器不知道客户端是什么状态,客户端的每一请求都是独立的,服务器根据请求,响应客户端的请求,但不会记录任何客户端信息

    2. HTTP协议的结构

    1.1 请求报文(Request) - 浏览器给服务器发

    请求报文由四部分组成:

    请求行:说明请求类型、要访问的资源, 以及使用的http版本请求头(报文头):说明服务器要使用的附加信息空行:此空行是一个\r\n,空行是必须要有的, 即使没有请求数据请求数据(报文主体):可以添加任意的其他数据

    HTTP1.1最常用的两种请求方法:

    GET ——请求指定的页面信息,并返回实体主体。POST——向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。

    上面图片是POST方法,它的请求行URL段中一般是没有参数的,参数放在了报文体中。而GET方法的参数直接置于请求行URL中,报文体则为空。

    1.2 HTTP 中, POST 与 GET 的区别

    Get是从服务器上获取数据,Post是向服务器传送数据。

    Get是把参数数据队列加到提交表单的Action属性所指向的URL中,值和表单内各个字段一一对应,在URL中可以看到。

    Get传送的数据量小,不能大于2KB;Post传送的数据量较大,一般被默认为不受限制。

    根据HTTP规范,GET用于信息获取,而且应该是安全的和幂等的。

    I. 所谓 安全的 意味着该操作用于获取信息而非修改信息。换句话说,GET请求一般不应产生副作用。就是说,它仅仅是获取资源信息,就像数据库查询一样,不会修改,增加数据,不会影响资源的状态。

    II. 幂等的 意味着对同一URL的多个请求应该返回同样的结果。

    1.3 响应报文(Response) - 服务器给浏览器发

    响应报文由四部分组成:

    状态行: 包括http协议版本号, 状态码, 状态信息消息报头: 说明客户端要使用的一些附加信息空行: 空行是必须要有的响应正文: 服务器返回给客户端的文本信息

    常用状态码: 状态代码有三位数字组成,第一个数字定义了响应的类别,共分五种类别:

    1xx:指示信息–表示请求已接收,继续处理2xx:成功–表示请求已被成功接收、理解、接受3xx:重定向–要完成请求必须进行更进一步的操作4xx:客户端错误–请求有语法错误或请求无法实现5xx:服务器端错误–服务器未能实现合法的请求

    常见状态码:

    200 OK 客户端请求成功400 Bad Request 客户端请求有语法错误,不能被服务器所理解401 Unauthorized 请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用403 Forbidden 服务器收到请求,但是拒绝提供服务404 Not Found 请求资源不存在,eg:输入了错误的URL500 Internal Server Error 服务器发生不可预期的错误503 Server Unavailable 服务器当前不能处理客户端的请求,一段时间后可能恢复正常

    3. web服务器端伪代码

    //响应消息头 void http_respond_head(int cfd, char* type){ char buf[1024]; // 状态行 sprintf(buf, "http/1.1 200 OK\r\n"); write(cfd, buf, strlen(buf)); // 消息报头 sprintf(buf, "Content-Type: %s\r\n", type); write(cfd, buf, strlen(buf)); // 空行 write(cfd, "\r\n", 2); } void main(){ // 修改进程的工作目录(这样就可以直接获取客户端要求的文件) chdir(path); // 创建监听的套接字 int lfd = socket(af_inet, sock_stream, 0); // 绑定 struct sockaddr_in serv; serv.family = af_inet; serv.port = htons(8989); bind(lfd, &serv, len); // 监听 listen(); int cfd = accept(); // 读数据 read(cfd, buf, sizeof(buf)); // 先将buf中的请求行拿出来 // GET /hello.c http/1.1 char method[12], path[1024], protocol[12]; // 得到文件名 char* file = path+1; //+1是为了去掉"/" // 打开文件 int fdd = open(file, O_RDONLY); int len = 0; //构建http响应头 http_respond_head(cfd, "text/plain"); // 循环读数据 >0 说明数据没读完 while( (len=read(fdd, buf, sizeof(buf))) > 0) { // 数据发送给浏览器 write(fdd, buf, len)); } }
    Processed: 0.020, SQL: 9