Socket编程日志 Week5

Socket编程日志 Week5

梦猫 Lv2

一、实验概要

第五周的实验需要实现服务器对 CGI 请求的支持,并能在 CGI 请求出错时返回对应的错误信息。
具体而言,对于 CGI 请求,服务器需要先对其表单的输入、对应 CGI 处理脚本的路径等信息进行解析,并据此配置 CGI 程序的环境变量。随后,服务器需要创建一个新线程,执行外部的 CGI 处理程序来生成响应,获取到响应并发送给客户端。此外,若在整个 CGI 处理过程中出现了任何错误,服务器都向客户端发送 500 报错信息。

二、协议设计

1. CGI 请求检测模块

此判断模块依附于 GET/HEAD 请求之下,若为这两种请求,则根据请求的 URI 判断是否为 CGI 请求。如果符合 CGI 请求格式,则调用 CGI 处理模块并进行响应,否则按普通的 GET/HEAD 请求进行处理。

2. CGI 处理模块

本模块首先从请求中提取出 CGI 脚本路径等必要信息,并调用环境变量配置模块进行 环境配置。随后,需要开辟一个新线程来运行 CGI 程序,并将 CGI 程序生成的响应存储至缓冲区中,以发送给客户端。此外,若处理过程中产生错误,则应返回错误,以向客户端发送 500 错误信息。

数据结构设计

首先,需要了解 CGI 请求的 URI 结构,以便从中提取所需信息。URI 共由 3 部分构成, 为/cgi-bin/,path 和 query。分别代表脚本的目录路径(也用于标识 CGI 请求),脚本路径和表单读取数据。具体结构如下方伪代码所示。

CGI uri
1
Request->uri:  /cgi-bin/path?query1&query2&……

此外,本模块中需要创建新线程来运行CGI程序,因此还需要了解线程管理相关的pid等数据结构。同时,在CGI程序进程和服务器程序进程进行通信时,需要使用到pipe(管道通信)。pipe的数据结构为一个二维int型数组,0和1分别存储标识读端口和写端口的标识号,可以借助如下伪代码进行理解。

pthread pipe
1
线程1/读端口  my_pipe[0] ========= my_pipe[1]  线程2/写端口
协议规则设计

了解以上数据结构后,可以按如下步骤进行CGI请求处理:
1. 根据URI获取CGI脚本文件路径;
2. 调用配置模块配置CGI程序环境变量
3. 创建子线程,在子线程中根据脚本路径运行CGI脚本
4. 创建管道,子线程将生成的响应写入管道
5. 父进程从管道中读取响应
6. 父进程将响应写入缓冲区中

根据以上设计,可以得到CGI请求处理流程图如下。

CGI Handle
CGI Handle

3. 环境变量配置模块

数据结构设计

此部分需要针对环境变量设计一个数据结构。考虑到每个环境变量都为一个固定格式的字符串,因此采用一个字符串数组在存储环境变量,每个元素均用于存储一个环境变量。
此外,此部分中许多环境变量需要从请求的Request结构体中获取,不过这一结构在前面已介绍过,故不再赘述。

协议规则设计

此模块主要是对各个环境变量进行配置,需要自行设计的内容较少,且在手册中有十分详细的介绍,不再赘述。

三、协议实现

1. CGI 请求检测模块

在实现上,前面提到过,对CGI请求的检测可以通过URI来完成。若某个HTTP GET/HEAD请求的URI起始为“/cgi-bin/”,则可认为其为一个CGI请求。此外,如果CGI处理模块返回错误,则向客户端响应500错误信息。调用CGI处理模块后的响应、报错等部分则与GET/HEAD请求的处理类似。

2. CGI 处理模块

首先,需要实现对CGI脚本文件的获取。前面提到过,在请求的URI中可以获取到脚本文件的路径,但其为“/cgi-bin/path”的形式,直接按此作为路径查找会进入系统文件夹。因此,出于实验的简单考量,可以对路径进行一定修改,使其变为在当前目录下的相对路径,再在实验目录下创建“cgi-bin”文件夹,并将所有脚本文件存储在其中即可。下面给出一个地址转换的例子。

addr trans
1
2
Request->uri:    /cgi-bin/path
Path to Locate: ./cgi-bin/path

其余部分只需参照前面的设计进行实现即可。

3. 环境变量配置模块

环境变量的配置方法在手册中已有详细说明,只需按照手册要求逐条配置,最后将其存储在前面设计的数据结构中,传入CGI处理程序中即可。因此在此不再展开。

4. HTML及CGI脚本文件

在本次实验中,还需要编写一个HTML文件,来展示一个可以填写表单的网页。此外,还需要编写对应的CGI脚本文件(使用Python编写),来根据表单中获取的数据生成动态网页。这两部分涉及到的知识与Socket编程关系较弱,且这两部分内容也较为简单,因此在此不再展开介绍这两个文件的设计和实现。

结果分析

浏览器测试(表单已填写)

Static Page 1
Static Page 1

CGI Page 1
CGI Page 1

浏览器测试(表单未填写)

Static Page 2
Static Page 2

CGI Page 2
CGI Page 2

实验总结

接触、了解了CGI程序及其功能,明白了如何根据用户的填写动态生成网页,以实现多样的应用层功能。

  • Title: Socket编程日志 Week5
  • Author: 梦猫
  • Created at : 2024-07-01 00:31:39
  • Updated at : 2024-07-04 22:08:03
  • Link: https://mengmaor.github.io/2024/07/01/Socket编程记录-Week5/
  • License: All Rights Reserved © 梦猫