文章目录
项目开发流程
程序编码
项目实例
项目开发流程
- 需求分析:实现基本的HTTP服务器,支持浏览器的访问(支持标准http协议)
- 接收浏览器发送HTTP请求;
- 解析请求数据,请求方式(GET),请求文件(html…),协议版本;
- 根据请求构建响应头,发送响应头:
- HTTP/1.1 200 Ok
- HTTP/1.1 404 File not found
- 根据请求文件,从服务器目录中获取对应的文件,发送给浏览器。
- 概要设计:绘制基本框图
- 详细设计:绘制程序流程图
web整体框架总流程
最外层流程
程序读取配置文件流程
子进程处理客户端请求流程
服务器初始化流程
正常请求响应流程
响应404流程
4. 编码:编写程序代码
程序编码
- 创建TCP并发服务器(多进程、多线程)
- 从配置中读取端口号–>将端口号写入配置文件configure中,创建服务器时从配置文件中读取端口号。(在启动服务器时添加-b选项使得服务器工作在守护进程模式)
int sockfd = socket(AF_INET,SOCK_STREAM,0); if(-1 == sockfd){ perror("socket"); return -1; } struct sockaddr_in server_addr; server_addr.sin_famlily = AF_INET; server_addr.sin_port = htons(8080) server_addr.sin_addr.s_addr = INADDR_ANY; if(bind(sockfd,(struct sockaddr*)&server_addr, sizeof(server_addr)) == -1){ perror("bind"); return -1; } listen(sockfd,10); //准备和客户端通信的socket套接字 int client_fd; struct sockaddr_in client_addr; socklen_t len = sizeof(client_addr); client_fd = accept(sockfd,&client_addr,&len); //创建子进程fork //创建子线程pthread_create char buf[1024]={0}; read(client_fd,buf,1024); puts(buf);//客户端发来的请求信息
- 接收客户端请求,打印请求数据,了解浏览器发来的请求数据包的内容。
- 解析请求数据包,保存必要数据
typedef struct{ char method[12];//请求方法,GET char path[128]; //请求文件,http、jpg.. char protocol[20];//请求协议版本,HTTP/1.1 }request_t;
- 创建响应头结构体
typedef struct{ int status;//状态码 200,404 char protocol;//协议版本,HTTP/1.1 char file_type[32];//类型信息 }response_t
- 从服务器目录(www)查找请求文件是否存在,存在则返回status=200,否则status=404.
- 构建响应头
协议版本:与请求行获取的协议版本一致 类型信息:根据请求的文件后缀匹配 eg: 如果客户请求是html文件,类型信息为"text/html" 同理支持如下类型: *.html --> "text/html" *.jpg/*.jpeg --> "image/jpeg" *.png --> "image/png" *.gif --> "image/gif" *.css --> "text/css" ...
- 发送响应头给客户端
eg: write("HTTP/1.1 200 OK\r\n"); write("Content-Type:text/html\r\n"); write("\r\n");
- 发送请求的文件
/* 如果status==200,说明请求文件存在,打开文件将文件内容发送给http客户端。 如果status==404,说明请求文件不存在, 发送"www/error.html" */ int fd = open("要给浏览器发送的文件"); int bytes_read=0; int bytes_write=0; int buffer[1024] = {0}; char* ptr; while(bytes_read = read(fd,buffer,1024)){ if(bytes_read == -1){break;} else if(bytes_read > 0){ ptr = buffer; while(bytes_write = write(client_fd,ptr,bytes_read)){ if(bytes_write == bytes_read){//写完 break; } else{//只写一部分 ptr += bytes_write bytes_read -= bytes_write; } } } }
- 关闭连接
项目实例
- 测试结果: