博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux平台上部署Mongoose服务器的方法介绍
阅读量:7038 次
发布时间:2019-06-28

本文共 4511 字,大约阅读时间需要 15 分钟。

前言

Mongoose是一个开源web服务器程序,仅有mongoose.c和 mongoose.h两个文件,虽然小巧,但具备基本的web服务器的功能,同时Mongoose是用C编写的,因此非常适合应用到嵌入式设备中。

目前Mongoose可以支持嵌入到C/C++、Python、C#。本文主要介绍下如何在Linux环境下将Mongoose代码嵌入到C应用程序中,并完成服务器的部署工作。
为了更快地熟悉web服务器的特性,在介绍部署服务器之前,有必要先介绍下服务器和客户端之间网络通讯的基础传输技术。


TCP连接过程

浏览器与Web服务器之间的请求和响应是使用HTTP协议进行的,但HTTP协议只是应用层使用的协议,传输层进行的数据通信则是通过TCP协议来保证的。

TCP协议是面向连接的协议,总体包括建立连接、数据传输和关闭连接这三个过程,建立连接采用“三次握手”方式来完成,连接成功后即可发送数据,在关闭连接之前,为确保数据正确传递完毕,需要采用“四次挥手”方式关闭连接。下面来分析下“三次握手”和“四次挥手”的过程。

1、客户端(192.20.1.12)“三次握手”连接服务器(192.20.1.122)

图片描述

  • 第一次握手:客户端发送连接请求报文段至服务器
SYN(flag)=1,表示客户端要求建立连接
Seq=x,随机产生序号
  • 第二次握手:服务器收到报文后确认连接请求,向客户端返回应答报文
SYN(flag)=1
ACK(flag)=1,表示服务器确认请求
ACK(num) =x+1(客户端Seq+1)
Seq=y,随机产生序号
  • 第三次握手:客户端收到响应后检查ACK(num)和ACK(flag)值,并向服务器给出确认
ACK(flag)=1,检查正确,客户端发送确认
ACK(num) =y+1(服务器Seq+1),客户端发送确认号
Seq=x+1
  • 完成三次握手,客户端与服务器开始传送数据

2、客户端(192.20.1.12)与服务器(192.20.1.122)“四次挥手”断开连接。客户端与服务器均可主动发起断开TCP连接请求,此处以客户端发起请求为例。

图片描述

  • 第一次挥手:客户端发送释放请求报文段至服务器,并不在发送数据
FIN(flag)=1,客户端要求终止连接
ACK(num)=z,上包数据Seq值
Seq=x,上包数据ACK(num)值
  • 第二次挥手:服务器收到释放连接请求后向客户端返回应答报文。此时连接处于半关闭状态,即客户端不再向服务器发送数据,但如果服务器仍有数据要发送给客户端,仍可以发送,客户端只要正确收到数据,仍应向服务器发送确认
ACK(flag)=1,表示服务器确认请求
ACK(num) =x+1(客户端Seq+1)
Seq=y,随机产生序号
  • 第三次挥手:若服务器不再向客户端发送数据,则服务器发送连接释放应答至客户端,关闭反方向连接
FIN(flag)=1,服务器要求终止连接
ACK(flag)=1,服务器发送确认
ACK(num) =x+1,与第二次挥手一致
Seq=y,与第二次挥手一致
  • 第四次挥手:客户端收到响应后向服务器给出确认,释放从服务器至客户端方向的连接。
ACK(flag)=1,检查正确,客户端发送确认
ACK(num) =y+1(服务器Seq+1),客户端发送确认号
Seq=x+1
  • 完成四次挥手,客户端与服务器全部连接完全释放

图片描述

也许有人会有疑惑,为什么建立连接协议是“三次握手”,而关闭连接却是“四次挥手”呢?由于TCP连接是全双工的,当关闭连接时,服务器收到客户端的FIN报文通知,仅仅表示客户端没有数据发送给服务器,但未必服务器所有的数据都发送给了客户端,可能还需要发送一些数据后再关闭连接。所以ACK报文和FIN报文分开发送形成了“四次挥手”。


Socket编程

在网络编程中不可避免地会使用到Socket编程,Socket将TCP/IP协议封装成API接口,

使得程序员更方便地使用TCP/IP协议栈。
Socket是以"打开—读/写—关闭"模式实现,以TCP协议通讯的Socket为例,交互流程大致如下,这里从服务器的角度对流程进行介绍:

图片描述

  • 创建socket()。socket()根据指定的协议族(IPv4/IPv6)、通信类型(TCP/UDP)在sockfs文件系统中分配一个使用socket描述字关联的资源,进程可以像访问一个已经打开的文件一样访问socket资源。
  • 绑定bind()。bind()在这个socket上绑定一个指定的端口号和IP地址。网络通信归根结底可视为不同计算机上的进程间通讯,IP地址只能确定进程所在的计算机,而结合端口号可以唯一确定整个网络中的一个网络进程。当IP地址为INADDR_ANY(0)时,表示本地计算机的默认IP地址。
  • 监听listen()。服务器socket端口一直处于等待状态,监听网络中所有客户端对端口号请求,随时准备接收客户端发来的连接
  • 接受accept()。服务器socket监听到客户端请求之后,将请求放在等待队列中,accept()从等待队列中提取连接请求,创建一个新的socket进行操作,而原来所监听的socket不受影响。
  • 读/写write()/read()。发送内容即向socket写入内容,读取内容即从socket获取内容
  • 关闭close()。close()关闭socket。

MakeFile

C程序的编译过程中,依次要进行预处理、编译、汇编、链接四个阶段,在Linux平台shell输入gcc命令完成上述步骤,但gcc在编译一个包含许多源文件的工程时,需要将其中的每个源文件都编译一遍,然后再全部连接起来,这样效率非常低,尤其当用户只是修改了其中某一个文件的时候,许多已经生成的目标文件是不会改变的,完全没有必要将每个文件都重新编译一遍。

为解决gcc编译的低效问题,Windows平台上的集成开发环境(IDE)提供了工程管理器,用户只需要点击一个“make”按钮就可以启动工程管理器对整个程序进行自动编译。
在Linux平台上,make工具和makefile提供了简单有效的工程管理方式。makefile决定编译工程的规则,通过make命令可以启动make工具根据makefile文件中的编译规对程序进行编译和链接,最终生成可执行文件。
Mongoose官网下载的源程序例程中提供了makefile文件,可以直接使用。

文件一:PROG = simplest_web_serverMODULE_CFLAGS=-DMG_DISABLE_DAV_AUTH -DMG_ENABLE_FAKE_DAVLOCKinclude ../examples.mk文件二:SUBDIRS = $(sort $(dir $(wildcard ./*/)))SUBDIRS:=$(filter-out ./ ./CC3200/ ./ESP32_IDF/ ./ESP8266_RTOS/ ./mbed/ ./MSP432/ ./nRF51/ ./nRF52/ ./NXP_K64/ ./NXP_LPC4088/ ./PIC32/ ./STM32F4_CC3100/ ./TM4C129/ ./WinCE/, $(SUBDIRS))ifeq ($(OS), Windows_NT)  SUBDIRS:=$(filter-out ./netcat/ ./raspberry_pi_mjpeg_led/ ./captive_dns_server/, $(SUBDIRS))endif.PHONY: $(SUBDIRS)all: $(SUBDIRS)$(SUBDIRS):    @$(MAKE) -C $@clean:    for d in $(SUBDIRS) ; do $(MAKE) -C $$d clean ; done

此处为了更好地说明makefile文件的功能,简单地编写了生成可执行文件的编译规则。将simplest_web_server.c mongoose.h编译成中间文件simplest_web_server.o,mongoose.c mongoose.h编译成中间文件mongoose.o,再将.o文件文件和所需的库文件链接成最终的可执行文件.all

all : simplest_web_server.o mongoose.o    gcc -o all simplest_web_server.o mongoose.o simplest_web_server.o :  simplest_web_server.c mongoose.h    gcc -c simplest_web_server.c    mongoose.o :  mongoose.c mongoose.h    gcc -c mongoose.c

Linux平台运行

Mongoose开源程序(官网下载6.9版本)提供了多个功能的例程,这里选用simplest_web_server(基础web服务器程序)的main函数作为主应用程序。

图片描述

创建Socket、绑定、监听等流程在以下函数中实现:

nc = mg_bind(&mgr, s_http_port, ev_handler);

循环mg_mgr_poll()遍历所有Socket,接受到新连接后进行数据收发,同时调用Socket相应事件处理函数。

for (;;) { mg_mgr_poll(&mgr, 1000); }

由用户实现的事件处理接口如下所示,可在该接口中实现服务器后台的业务逻辑功能:

static void ev_handler(struct mg_connection *nc, int ev, void *p) {  if (ev == MG_EV_HTTP_REQUEST) {    mg_serve_http(nc, (struct http_message *) p, s_http_server_opts);  }}

此处示例在mg_serve_http()中通过Linux文件系统查找index.html文件并返回给浏览器:

if (opts.index_files == NULL) {    opts.index_files = "index.html,index.htm,index.shtml,index.cgi,index.php";  }

将mongoose.h、mongoose.c和simplest_web_server.c拷贝到自己的程序目录下,同时将index.html也放置到该目录下。

图片描述

在Linux的Shell命令行输入make命令,make工具会自动寻找当前目录下的“makefile”文件进行解析,并生成最终的可执行文件.all,运行.all可启动web服务器程序。

图片描述

图片描述

在服务器本机的浏览器中输入:1200/来访问web服务器,如下图所示:

图片描述

通过另一台电脑的浏览器输入:1200/,如下图所示:

图片描述

转载地址:http://mkfal.baihongyu.com/

你可能感兴趣的文章
leetcode -- Word Break
查看>>
PYTHONPATH 可以跨版本 方便使用 (本文为windows方法)转~
查看>>
Oracle 动态视图5 V$SESSION_LONGOPS
查看>>
C中字符串分割函数strtok的一个坑
查看>>
虚拟主机配置
查看>>
强大的数据库查询工具Database.NET 9.4.5018.42
查看>>
China特色创新现状
查看>>
MySQL数据库(表)的导入导出(备份和还原)
查看>>
使用开源库 TWMessageBarManager 展示系统级别的通知
查看>>
仿人人滑动菜单
查看>>
Unity3.5 GameCenter基础教程(转载)
查看>>
.Net 转战 Android 4.4 日常笔记(8)--常见事件响应及实现方式
查看>>
libiconv2.dll
查看>>
[leetcode]Word Search @ Python
查看>>
Android学习---数据库的增删改查(sqlite CRUD)
查看>>
[leetcode]Gray Code @ Python
查看>>
开发网上支付的两种方式(图)
查看>>
log4e下载地址
查看>>
站点建设10个最好的响应的HTML5滑块插件
查看>>
设计模式(3)-对象创建型模式-Abstract Factory模式
查看>>