前面我们实现了TCP服务器和客户端的简单应用,接下来我们实现一个基于TCP协议的应用协议,那就是HTTP超文本传输协议
1、 HTTP协议简介
超文本传输协议(Hyper Text Transfer Protocol),简称HTTP,是一种基于TCP的应用层协议,也是目前为止最为流行的应用层协议之一,可以说HTTP协议是万维网的基石。
HTTP是一种客户端请求、服务器应答式的应用层传输协议,也就是说服务器端是不可能主动向客户端发送数据的。在网络正常的情况下请求和响应都是一一对应的。而这个请求和响应也就是后端开发人员经常看到的Request和Response。
首先,我们来看客户器端的请求,HTTP请求报文由请求行、请求头、空白行以及请求体组成。其报文格式如下:
我们来说一说请求行,它由请求方法字段、URL字段和HTTP协议版本字段3个字段组成,它们用空格分隔。需要理解的是请求方法,HTTP协议的请求方法有GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT几种。先对常用的几种说明如下:
客户端发出HTTP请求,服务端接收后,会向客户端发送响应信息。所以接下来,我们来看看服务器端的响应报文。HTTP响应报文由响应行、响应头、空白行以及响应体组成。其报文格式如下:
在响应报文中,非常重要的就是响应行,其中响应行中最重要的就是HTTP的状态码。HTTP协议中状态码有三位数字组成,第一位数字定义了响应的类别,有以下五种:
我们开发过程有一些状态码比较常见,我们对其简单说明如下:
2、 HTTP服务器端的设计
我们已经对基于RAW API的TCP应用有了了解。我们在实现TCP服务器的实验时就提到过对于更复杂的应用和应用层协议只是在功能上的差别,从实现的结构及流程来说是完全一致的。所以对于实现HTTP服务器需要使用到的函数及整个操作流程我们就不再叙述了。重点说一说不同的地方。
首先HTTP服务器是基于TCP的,所以其我们先将其当作TCP服务器来实现。需要注意的是,HTTP协议有其专门的操作端口:80。所以我们设计服务器时需要使用这个端口。
在这里,我们设计一个简单的HTTP服务器,当客户端连接到服务器之后,如果收到的是html请求,则返回一个我们预先设定好的网页。正常返回这个网页,HTTP的功能就完成了,HTTP服务器会主动断开与客户端的连接。
3、 TTP服务器实现
既然是基于TCP的HTTP服务器,我们佷显然依然按照TCP服务器的结构来实现。我们依然将其划分为三个部分来实现。首先要实现的是HTTP服务器的初始化。
1 /* HTTP服务器初始化配置*/ 2 void Http_Server_Initialization(void) 3 { 4 struct tcp_pcb *pcb = NULL; 5 6 /* 生成一个新的TCP控制块 */ 7 pcb = tcp_new(); 8 9 /* 控制块绑定到本地IP和对应端口 */ 10 tcp_bind(pcb, IP_ADDR_ANY, TCP_HTTP_SERVER_PORT); 11 12 /* 服务器进入侦听状态 */ 13 pcb = tcp_listen(pcb); 14 15 /* 注册服务器accept回调函数 */ 16 tcp_accept(pcb, HttpServerAccept); 17 18 }
从上面的代码不难看出,与TCP服务器的初始化一样:建立控制块,为控制块绑定本地IP和端口,服务器监听控制块同时注册接收处理回调函数。所以接下来就是实现接收处理回调函数。
1 /* HTTP接收回调函数,客户端建立连接后,本函数被调用 */ 2 static err_t HttpServerAccept(void *arg, struct tcp_pcb *pcb, err_t err) 3 { 4 /*注册HTTP服务器回调函数*/ 5 tcp_recv(pcb, HttpServerCallback); 6 7 return ERR_OK; 8 }
客户端连接成功后就会调用接收处理回调函数。该函数为tcp_accept_fn类型,注册到了监听控制块的accept字段。在这个函数中,我们需要注册HTTP服务器处理函数。其功能就由这个函数决定。
1 /* HTTP服务器信息处理回调函数 */ 2 static err_t HttpServerCallback(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) 3 { 4 char *data = NULL; 5 6 if (p != NULL) 7 { 8 /* 更新接收窗口 */ 9 tcp_recved(pcb, p->tot_len); 10 data = p->payload; 11 12 /* 如果是http请求,返回html信息,否则无响应 */ 13 if(p->len >=3 && data[0] == ‘G‘&& data[1] == ‘E‘&& data[2] == ‘T‘) 14 { 15 tcp_write(pcb, htmlMessage, sizeof(htmlMessage), 1); 16 } 17 else 18 { 19 20 } 21 pbuf_free(p); 22 tcp_close(pcb); 23 } 24 else if (err == ERR_OK) 25 { 26 return tcp_close(pcb); 27 } 28 return ERR_OK; 29 }
这个HTTP服务器非常简单,我们只是实现了GET方法。也就是说,收到客户端的html请求后,我们检测其要求,如果是GET方法,我们就返回预先设定好的网页,否则无返回。然后关闭这一连接。如果我们想要实现更复杂的功能,或者需要支持HTTP协议的其他方法,只需要扩展这个函数就可以了。
4、 结论
HTTP协议是一种使用非常广泛的协议,其基于TCP基础上运行,所以在我们前面已经实现TCP服务器及客户端的情况下,开发HTTP服务器应用就显得简单了。在这一篇我们基于LwIP实现了一个简单的HTTP服务器应用,我们并对其进行了简单的测试,虽然我们只是实现了GET方法,但经测试设计是正确的。如果需要设计其他方法的HTTP应用只需在此基础上添加即可。
欢迎关注:
原文:https://www.cnblogs.com/foxclever/p/12045235.html