引言
控制网络一般指以控制“事物对象”为特征的计算机网络系统,简称Infranet(infrastructure network),它处在企业网(Intranet)的底层,构成了整个企业网的基础。近些年来,在控制网络中采用了现场总线(Field Bus)和工业以太网(Ethernet)两种技术。出现这种情况主要有两个原因:第一,目前存在多种现场总线标准,不同的标准采用完全不同的通信协议,也就是说现场总线的开放性不够;第二,以太网虽然能够解决开放性的问题,并具备成本低廉、技术成熟等优点,但由于以太网最初是被设计用于以资源共享为目的的计算机局域网,因此在实时性和可靠性上暂时还不能完全满足工业控制的要求。事实上,目前一个较大规模的控制网络往往综合采用了这两种技术。在现场层,由于强调实时性、可靠性和安全性,常采用现场总线技术;在监控管理层,考虑到采用不同标准的控制网段之间的集成以及与高层企业信息网络的集成,一般采用以太网技术。现场层的现场总线控制系统FCS(Field Control System)或其它设备级轻质网络通过网关或嵌入式HTTP服务器与高层以太网相连。这样,不仅采用不同协议的控制网段能够实现互联,而且各个控制网段能方便地与高层企业信息网互通,从而最终实现企业网的管控一体化和对现场设备的Internet远程监控。通过以上分析可以看出,控制网络中的网关或嵌入式HTTP服务器起着连接现场层和监迭管理层的作用,因此它是整个控制网络的关键设备。
网关或嵌入式HTTP服务器与传统的嵌入式系统相比,有一些不同的特性。传统的嵌入式系统是面向应用、有一些不同的特性。传统的嵌入式系统是面向应用、面向产品的,强调成本和高效设计系统,因此本质上不具备通用性和可移植性。网关或嵌入式HTTP服务器由于处在现场层和监控管理层的中间,因此它与具体应用和产品是一种弱耦合的关系。同时,技术发展的趋势是:硬件成本越来越低,功能越来越强,越来越多的芯片和板卡具备“平台”的特点,适用于多种应用场合。嵌入式实时操作系统(Embedded Real Time Operationg System)的发展更是为嵌入式软件提供了一个通用的软件平台。综上所述,在网关或嵌入式HTTP服务器设计中,考虑通过选用适合的硬件和嵌入式实时操作系统,使整个系统具备相当的通用性和可移植性。对于连接不同的设备级轻质网络或不同的应用,只需要通过更换硬件模块和对代码作最小的修改即可实现。
1 基于Linux的嵌入式HTTP服务器的结构
为了实现设计目标,嵌入式HTTP服务器一般应采用功能较强的能用PC、工业PC、或高档MPU作为硬件平台,嵌入式实时操作系统作为软件平台进行平发。硬件平台应具备以太网口和一个或多个通信模块,比如RS232、RS485、CAN通信卡等。嵌入式实时操作系统实现了TCP/IP等网络协议,并提供实时任务、进程管理、内存管理、文件系统、API等功能。
Linux操作系统是一种多进程,多用户的通用操作。由于它具备免费、源码公开、内核可裁减、支持多线程、网络功能强大、设计精巧、性能稳定的特点,因此近年它也被广泛用到嵌入式系统的设计中。一个应用于嵌入式系统的Linux经过裁减和重新编译后只包括进程管理、内存管理、文件系统、若干个驱动程序和实用的函数等。
下面以本人参与的转子秤控制系统为例来说明一个基于Linux的嵌入式HTTP服务器的结构。转子秤是水泥工业中的关键计量喂料设备,一条大型的生产线需要许多台转子秤,对转子秤的控制涉及到重量、转速、温度、一氧化碳含量等若干个参量。由于现场环境的高噪声、高粉尘、高电磁干扰,无法在现场配备键盘、显示器、触摸屏等人机交互设备,无法在现场实现对设备的监控和维护。同时,一条生产线有多台转子秤,为每台转子秤配备人机交互设备也是不经济的。为此,考虑为整个系统设计一个嵌入式HTTP服务器,各转子秤控制器与嵌入式HTTP服务器用CAN总线相连。通过嵌入式HTTP服务器实现对整个系统的在线监控和远程监控。在嵌入式HTTP服务器的设计中,选用研祥公司PC104总线的486X嵌入式CPU卡作为硬件平台,该板卡是具有128MB的在板ROM、CF卡接口和以太网接口等。选择该板卡的原因是PC104总线的功能扩展模块非常丰富,通过选择不同的模块很容易就支持多种总线。软件平台方面,选用Linux2.0内核并对它作适当裁减。整个嵌入式HTTP服务器的结构简图如图1所示。
2 基于Linux的嵌入式HTTP服务器的设计
工控领域的嵌入式HTTP服务器应该具备如下基本功能。
①实时数据发布。实时数据主要包括系统运行过程中设备的各种状态信息。嵌入式HTTP服务器将实时数据以网页形式发布到Internet上,且动态实时刷新。客户可以通过浏览器访问这些实时信息。
②参数设置。参数包括运行参数和设备状态参数,如各种初始值、常数等。嵌入式HTTP服务器接收到客户提交的参数设备请求后,执行参数写入操作。
③远程实时控制。远程实时控制允许远程用户在线地控制系统中的相应执行机构,比如电机、电磁阀等。嵌入式HTTP服务器接收到远方客户提交的控制操作请求后,将下发控制命令驱动监控系统中相应的执行机构。
④访问级别设置和权限认证。只有权限不低于要求访问级别的客户,经嵌入式HTTP服务器认证后,方可进行其权限范围内的监控操作。
3 主要实现技术
3.1 超文本传输协议
HTTP协议是一个面向事务、无状态的应用层协议。在传输层,HTTP协议使用请求(request)/响应(response)模型。一次简单的HTTP事务包括以下过程。首先,客户(浏览器)发起和建立一条到服务器的TCP连接。然后,客户发送一个HTTP请求到服务器,请求包含方法、URI、协议版本和一个类MIME报文。服务器解析HTTP请求后,给出相应的HTTP响应,响应包括协议版本、状态码、解释状态码的简短短语和一个类MIME报文。最后,释放TCP连接。Linux操作系统为用户提供了称为BSD Socket的网络编程接口。利用其中的TCP套接口函数,可以非常方便地实现HTTP协议。
HTTP1.0为每一次HTTP请求/响应建立一条新的TCP连接,由于建立一条TCP连接要经历3次握手,因此效率不高。HTTP1.1提出了可持续性连接的概念。HTTP1.1只建立一次TCP连接,而重复地使用它传送一条素的请求/响应消息,减少了额外开销。在嵌入式HTTP服务器中,一般使用HTTP1.1协议。HTTP1.1协议的细节请参考RFC2616。
3.2 通用网关接口CGI
参数设置和远程控制功能都是通过CGI(通用网关接口)程序和表单实现的。CGI使用HTML表单向Web服务器发送信息。基本语法如下:
<FORM METHOD=get/post ACTION=URL></FORM>
其中,METHOD属性指定将数据传送到Web服务器的方法。输入方法有两种:GET和POST。ACTION属性定义要对表单数据进行处理的CGI脚本的URL。
CGI的工作流程是首先由浏览器将用户输入的数据传递给Web服务器,Web服务器根据接收到的数据设置环境变量并启动CGI脚本,CGI脚本从环境变量中读取所需要的数据并进行相应处理,最后使用STDOUT输出HTML形式的结果文件,经Web服务器送回浏览器,最终显示给用户。传统的CGI程序与服务器代码分开,是一个符号CGI标准的可执行文件,并储存在CF卡等存储设备上,一般用脚本语言编写。考虑到嵌入式HTTP服务器要求速度快,功能和代码都尽可能精简的特点,可以把原先由可执行文件完成的功能用C函数实现,放在服务器代码内部,并直接从HTTP请求报文接收数据。与传统CGI程序相比,这种方法具备如下特点:
*不需要标准输入,CGI函数可以直接获取到浏览器送来的信息;
*不需要标准输出,CGI函数可以直接将数据送回给浏览器;
*不需要环境变量,CGI和Web服务器在同一程序中实现,不需要环境变量来交换信息。
3.3 自定义标记
要在网页中显示工控系统中大量的实时数据,常规方法是将HTML代码直接集成到程序代码中,或者反之将C程序代码集成到HTML标记语言中。这两种方法均要求开发人员对HTML标记语言的语法细节非常熟悉。网页或程序结构的单方面调整都将导致整个系统全盘修改,系统不具备灵活性与可扩展性。HTML的精髓在于该语言的“标记”性,各种不同标记的具体含义是由服务器和浏览器进行解析。因此,当现有标记不能满足新的应用需求时,可以自行定义新的标记,只需服务器将自定义标记解析为标准标记,然后传送给浏览器即可。在本项目中,主要的实时数据转速、重量、一氧化碳含量等状态信息,可以定义相应的标记。服务器中解析相应标记的函数同样用C语言来实现。运行时,当客户端发出查看某实时网页的请求后,嵌入式HTTP服务器将相应的网页文件从电子盘加载到内存进行逐项解析。当辨识出自定义标记后,就调用相应的函数。该函数返回该标记对应的当前值,并置换HTML文件流中的自定义标记。最后,嵌入式HTTP服务器将解析结果发送给客户端。实时网页的设计与相应的HTTP服务器处理程序得以分离,处于一种弱耦合关联状态。这样,网页界面的调整不会影响HTTP服务器的程序设计,HTTP服务器程序的修改也与网页界面设计无关,整个嵌入式HTTP服务器具备灵活性和可扩展性。
3.4 多线程
最初的进程定义包含程序、资源及其执行三部分,其中程序通常指代码,资源通常包括 内存资源、I/O资源、信号处理等,而程序的执行指执行上下文,这一部分后来发展为线程。在线程的概念出现以前,为了减小进程切换的开销,操作系统设计者逐渐修改正进程的概念,允许将进程所占有的资源从其主体剥离出来,允许某些进程共离享一部分资源,例如文件、信号、数据内存、甚至代码,这就是轻质进程的概念。Linux内核的2.0.x版本就已经实现了轻质进程。应用程序可以通过一个统一的clone()系统调用接口,用不同的参数指定创建轻质进程还是普通进程。在内核中,clone()调用经过参数传递和解释后会调用do_fork(),这个核内函数同时也是fork、vfork()系统调用的最终实现。在do_fork()中,不同的flone_flags将导致不同的行为。在LinuxThreads中,使用(CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND)参数调用clone()创建“线程”,表示共享内存、共享文件系统、共享文件描述符表,以及共享信号处理方式。Linux操作系统下,已经实现基于轻质进程的符号POSIX1003.C标准的线程库LinuxThreads。
在传统的Unix服务器程序设计中,为了使服务器具备并发处理连接的能力,通常采用父进程处理连接,并调用fork()创建子进程来处理用户请求的方法。这种方法的缺点是进程创建慢,耗费资源,进程切换开销大,进程之间通信比较困难等,不适用对资源、速度有要求的嵌入式系统。因此,在嵌入式HTTP服务器的开发中使用线程的方法。利用LinuxThreads提供的pthread_create()等函数派生出线程,也即轻质进程来处理多个HTTP请求。
4 工作流程和代码设计
4.1工作流程
嵌入式HTTP服务器程序开始运行时,主进程首先创建一个接口,并和主机地址绑定到一起,随后置为被动监听状态,等待客户端连接请求的到来。分别用函数socket()创建一个接口,bind()绑定地址,listen()监听,accept()接收来完成。当建立一个TCP连接后,函数accept()返回一个新的套接口描述符,主进程就创建一个新的子线程(轻质进程)处理这个新的连接。
子线程用于处理每具体的HTTP请求。子线程首先解析用户的HTTP请求。当用户请求一个网页时,子线程查找文件系统。如果该网页文件存在,且通过权限认证,就把它从CF卡读入内存并扫描,发现有自定义标记则调用相应函数进行处理,最后把结果返回给浏览器;否则给一个简单的出错消息。当用户是上传数据时,子线程调用相应函数读取数据进行处理,并返回处理结果给浏览器。
4.2 代码设计
在嵌入式HTTP服务器的代码设计中,考虑到代码的移植性和扩展性,利用C语言实现了面向对象风格的代码结构。代码主要由两上数据结构request_inf和response_inf以及其上一组操作函数组成。
结构request_inf和response_inf分别用来保存HTTP请求报文和响应报文的所有信息。在结构定义时,应根据具体应用特点设计结构包含的成分。
嵌入式HTTP服务器的函数包括通用函数、CGI函数和自定义标记处理函数等,其中通用函数是一些与HTTP1.1协议有关的函数。
(1)通用函数
*void prase_request_line(char *,struct *request_inf)
该函数用来解析HTTP请求报文的请求行(Request_Line),并把相应信息存放在结构request_inf中。其中,对请求行中URI部分的解析包括两种情况。如果用户请求一个网页,则获取文件路径、文件类型;如果用户要求上传数据,则把数据放在一个字符数组中。然后将文件路径和类型,或者指向该数组的指针、方法、版本号信息都放入结构request_inf中。
*void prease_general_header(char*,struct*request_inf)
该函数用来解析HTTP请求报文的调用首部(General_Header)。之所以把此函数与函数prase_request_line()分开,是考虑到程序的修植性和扩展性。请求行和通用首部是请求报文中的不同部分,不不同的场合下,要求解析的信息可能存在差导师。同时,这样也能使程序结构更清楚。比如,本项目要从通用首部解析字段Keep_Alive。该字段指明一个最长的时间或最大请求数目,在此范围内可以保持TCP连接不被释放(即前文提到的HTTP1.1的持续连接特性,persistent connection)。
*void prase_request_header(char*,struct*request_inf)
void prase_entity_header(char*,struct*request_inf)
HTTP请求报文的请求头部用来说明浏览器的一些信息,实体头部则用来说明请求报文中可能存在的实体主体信息。本项目实际上并不需要使用这两个函数来获取相关信息,但考虑到程序的扩展性和移植性,此处仍然把它列出来,它们是两个空函数。
*send_status_line(int fd,struct *response_inf)
此函数用来产生一个HTTP响应报文的状态行(Status_line)。状态行包括三部分内容,即HTTP版本、状态码以及解释状态码的简单短语。这些信息预先放在结构response_inf中。
*send_general_header(int fd,struct*response_inf)
send_response_header(int fd,struct*response_inf)
send_entity_header(int fd,struct*response_inf)
这三个函数分别用来产生HTTP响应报文的通用首部、响应首部(Response_header)和实体首部。嵌入式HTTP服务器是一个瘦服务器,功能非常简单。因此HTTP响应报文的通用首部、响应首部和实体首部中的可选字段许多是不需要的,还有许多是固定不变的,例如Last_modified和Content_type字段。Last_modified字段指出资源上次被修改的时间并由接收方解释。如果接收方已有此资源的拷贝,但此拷贝比Last-Modified域所指定的要旧,那该拷贝就是过期的。由于网页文件中含有自定义标记,具有实时性,所以此字段根本没有含有Content_type字段指出实体的媒体类型,本项目中的嵌入式HTTP服务器被设计成只支持HTML类型,因此该字段的内容总是Content_type=text/html。有关服务器和资源的所有标题域信息都被放入结构response_inf中。
*send_white_line(int fd)
此函数用于实体首部和实体之间传送一个空白行。
*void send_entity_body(int fd,char *buff_file)
此函数用来传递实体主体,实体主体实际上是一个处理后的网页文件,它被放在指针buff_file指向的缓冲区内。
*void zero_request_inf(struct*request_inf)
void zero_response_inf(struct*response_inf)
这两个函数用于结构request_inf和response_inf清零。
*void get_file(struct*request_inf,struct * response_inf,char*buff_file,void*,void*)
该函数用来处理用户HTTL请求。首先,函数会检查request_inf结构,判断用户是请求一个网页文件还是上传数据。当用户请求网页文件时,函数将根据request_inf结构中的文件路径信息,在文件系统录找此文件。如果文件不存在或不具备权限,则函数将状态码和解释短语写入结构response_inf,然后直接返回;否则读取文件并调用自定义标记处理函数,对标记进行处理,处理过的网页文件被放入buff_file指向的缓冲区内,并把状态码、解释短路和与实体有关的一些信息写入结构response_inf。当用户上传数据时,该函数调用CGI处理函数向CAN总线网络发送帧,然后将状态码和解释短路写入结构response_inf。利用状态码和解释短语只能用“200,OK”或“500,Internal Server Error”等,简单反映执行情况。用户要获取详细信息,可待一段合适的时间后请求网页文件。函数中两个void指针分别指向自定义标记处理函数和CGI处理函数,或者对应的函数指针数组。
(2)自定义标记处理函数和CGI处理函数
自定义标记处理函数用于对自定义的处理,每一类自定义标记对对应一种自定义标记处理函数,同一类自定义标记的不同数据点利用参数来区分,比如转子秤1的重量标记可以用weight1来表示。所有的自定义标记处理函数被放在一起,构成一个函数指针数组。自定义标记处理函数向CAN总线网络发送远程帧和接收数据帧,获取相应的状态信息。CGI总线网络发送远程帧和接收数据帧,获取相应的状态信息。CGI处理函数用变量名来区分,同一类变量对应一种CGI处理函数。与自定义标记处理函数类似,所有的CGI处理函数也被放在一起,构成一个函数指针数组。由于自定义标记函数和CGI处理函数类型众多,这里就不列举了。
结语
我们设计的嵌入式HTTP服务器具备良好的通用性和可移植性。通过更换或增加PC104通信模块,该服务器能够支持不同的现场总线,或同时连接几种不同的设备级轻质网络。同时在服务器代码设计中,用C语言实现了面向对象风格的代码结构。这样,如果要求服务器端具备更多的特性,只需要简单修改结构request_inf、response_inf、操作函数和网页文件即可达到目的。这种设计思路不仅适用于嵌入式HTTP服务器,随着硬件技术尤其是嵌入式操作系统技术的发展,它同样能够应用到其它嵌入式产品的开发中。
关键字:嵌入式HTTP服务器 Linux 控制网络
引用地址:工控网中基于Linux的嵌入式HTTP服务器设计
控制网络一般指以控制“事物对象”为特征的计算机网络系统,简称Infranet(infrastructure network),它处在企业网(Intranet)的底层,构成了整个企业网的基础。近些年来,在控制网络中采用了现场总线(Field Bus)和工业以太网(Ethernet)两种技术。出现这种情况主要有两个原因:第一,目前存在多种现场总线标准,不同的标准采用完全不同的通信协议,也就是说现场总线的开放性不够;第二,以太网虽然能够解决开放性的问题,并具备成本低廉、技术成熟等优点,但由于以太网最初是被设计用于以资源共享为目的的计算机局域网,因此在实时性和可靠性上暂时还不能完全满足工业控制的要求。事实上,目前一个较大规模的控制网络往往综合采用了这两种技术。在现场层,由于强调实时性、可靠性和安全性,常采用现场总线技术;在监控管理层,考虑到采用不同标准的控制网段之间的集成以及与高层企业信息网络的集成,一般采用以太网技术。现场层的现场总线控制系统FCS(Field Control System)或其它设备级轻质网络通过网关或嵌入式HTTP服务器与高层以太网相连。这样,不仅采用不同协议的控制网段能够实现互联,而且各个控制网段能方便地与高层企业信息网互通,从而最终实现企业网的管控一体化和对现场设备的Internet远程监控。通过以上分析可以看出,控制网络中的网关或嵌入式HTTP服务器起着连接现场层和监迭管理层的作用,因此它是整个控制网络的关键设备。
网关或嵌入式HTTP服务器与传统的嵌入式系统相比,有一些不同的特性。传统的嵌入式系统是面向应用、有一些不同的特性。传统的嵌入式系统是面向应用、面向产品的,强调成本和高效设计系统,因此本质上不具备通用性和可移植性。网关或嵌入式HTTP服务器由于处在现场层和监控管理层的中间,因此它与具体应用和产品是一种弱耦合的关系。同时,技术发展的趋势是:硬件成本越来越低,功能越来越强,越来越多的芯片和板卡具备“平台”的特点,适用于多种应用场合。嵌入式实时操作系统(Embedded Real Time Operationg System)的发展更是为嵌入式软件提供了一个通用的软件平台。综上所述,在网关或嵌入式HTTP服务器设计中,考虑通过选用适合的硬件和嵌入式实时操作系统,使整个系统具备相当的通用性和可移植性。对于连接不同的设备级轻质网络或不同的应用,只需要通过更换硬件模块和对代码作最小的修改即可实现。
1 基于Linux的嵌入式HTTP服务器的结构
为了实现设计目标,嵌入式HTTP服务器一般应采用功能较强的能用PC、工业PC、或高档MPU作为硬件平台,嵌入式实时操作系统作为软件平台进行平发。硬件平台应具备以太网口和一个或多个通信模块,比如RS232、RS485、CAN通信卡等。嵌入式实时操作系统实现了TCP/IP等网络协议,并提供实时任务、进程管理、内存管理、文件系统、API等功能。
Linux操作系统是一种多进程,多用户的通用操作。由于它具备免费、源码公开、内核可裁减、支持多线程、网络功能强大、设计精巧、性能稳定的特点,因此近年它也被广泛用到嵌入式系统的设计中。一个应用于嵌入式系统的Linux经过裁减和重新编译后只包括进程管理、内存管理、文件系统、若干个驱动程序和实用的函数等。
下面以本人参与的转子秤控制系统为例来说明一个基于Linux的嵌入式HTTP服务器的结构。转子秤是水泥工业中的关键计量喂料设备,一条大型的生产线需要许多台转子秤,对转子秤的控制涉及到重量、转速、温度、一氧化碳含量等若干个参量。由于现场环境的高噪声、高粉尘、高电磁干扰,无法在现场配备键盘、显示器、触摸屏等人机交互设备,无法在现场实现对设备的监控和维护。同时,一条生产线有多台转子秤,为每台转子秤配备人机交互设备也是不经济的。为此,考虑为整个系统设计一个嵌入式HTTP服务器,各转子秤控制器与嵌入式HTTP服务器用CAN总线相连。通过嵌入式HTTP服务器实现对整个系统的在线监控和远程监控。在嵌入式HTTP服务器的设计中,选用研祥公司PC104总线的486X嵌入式CPU卡作为硬件平台,该板卡是具有128MB的在板ROM、CF卡接口和以太网接口等。选择该板卡的原因是PC104总线的功能扩展模块非常丰富,通过选择不同的模块很容易就支持多种总线。软件平台方面,选用Linux2.0内核并对它作适当裁减。整个嵌入式HTTP服务器的结构简图如图1所示。
2 基于Linux的嵌入式HTTP服务器的设计
工控领域的嵌入式HTTP服务器应该具备如下基本功能。
①实时数据发布。实时数据主要包括系统运行过程中设备的各种状态信息。嵌入式HTTP服务器将实时数据以网页形式发布到Internet上,且动态实时刷新。客户可以通过浏览器访问这些实时信息。
②参数设置。参数包括运行参数和设备状态参数,如各种初始值、常数等。嵌入式HTTP服务器接收到客户提交的参数设备请求后,执行参数写入操作。
③远程实时控制。远程实时控制允许远程用户在线地控制系统中的相应执行机构,比如电机、电磁阀等。嵌入式HTTP服务器接收到远方客户提交的控制操作请求后,将下发控制命令驱动监控系统中相应的执行机构。
④访问级别设置和权限认证。只有权限不低于要求访问级别的客户,经嵌入式HTTP服务器认证后,方可进行其权限范围内的监控操作。
3 主要实现技术
3.1 超文本传输协议
HTTP协议是一个面向事务、无状态的应用层协议。在传输层,HTTP协议使用请求(request)/响应(response)模型。一次简单的HTTP事务包括以下过程。首先,客户(浏览器)发起和建立一条到服务器的TCP连接。然后,客户发送一个HTTP请求到服务器,请求包含方法、URI、协议版本和一个类MIME报文。服务器解析HTTP请求后,给出相应的HTTP响应,响应包括协议版本、状态码、解释状态码的简短短语和一个类MIME报文。最后,释放TCP连接。Linux操作系统为用户提供了称为BSD Socket的网络编程接口。利用其中的TCP套接口函数,可以非常方便地实现HTTP协议。
HTTP1.0为每一次HTTP请求/响应建立一条新的TCP连接,由于建立一条TCP连接要经历3次握手,因此效率不高。HTTP1.1提出了可持续性连接的概念。HTTP1.1只建立一次TCP连接,而重复地使用它传送一条素的请求/响应消息,减少了额外开销。在嵌入式HTTP服务器中,一般使用HTTP1.1协议。HTTP1.1协议的细节请参考RFC2616。
3.2 通用网关接口CGI
参数设置和远程控制功能都是通过CGI(通用网关接口)程序和表单实现的。CGI使用HTML表单向Web服务器发送信息。基本语法如下:
<FORM METHOD=get/post ACTION=URL></FORM>
其中,METHOD属性指定将数据传送到Web服务器的方法。输入方法有两种:GET和POST。ACTION属性定义要对表单数据进行处理的CGI脚本的URL。
CGI的工作流程是首先由浏览器将用户输入的数据传递给Web服务器,Web服务器根据接收到的数据设置环境变量并启动CGI脚本,CGI脚本从环境变量中读取所需要的数据并进行相应处理,最后使用STDOUT输出HTML形式的结果文件,经Web服务器送回浏览器,最终显示给用户。传统的CGI程序与服务器代码分开,是一个符号CGI标准的可执行文件,并储存在CF卡等存储设备上,一般用脚本语言编写。考虑到嵌入式HTTP服务器要求速度快,功能和代码都尽可能精简的特点,可以把原先由可执行文件完成的功能用C函数实现,放在服务器代码内部,并直接从HTTP请求报文接收数据。与传统CGI程序相比,这种方法具备如下特点:
*不需要标准输入,CGI函数可以直接获取到浏览器送来的信息;
*不需要标准输出,CGI函数可以直接将数据送回给浏览器;
*不需要环境变量,CGI和Web服务器在同一程序中实现,不需要环境变量来交换信息。
3.3 自定义标记
要在网页中显示工控系统中大量的实时数据,常规方法是将HTML代码直接集成到程序代码中,或者反之将C程序代码集成到HTML标记语言中。这两种方法均要求开发人员对HTML标记语言的语法细节非常熟悉。网页或程序结构的单方面调整都将导致整个系统全盘修改,系统不具备灵活性与可扩展性。HTML的精髓在于该语言的“标记”性,各种不同标记的具体含义是由服务器和浏览器进行解析。因此,当现有标记不能满足新的应用需求时,可以自行定义新的标记,只需服务器将自定义标记解析为标准标记,然后传送给浏览器即可。在本项目中,主要的实时数据转速、重量、一氧化碳含量等状态信息,可以定义相应的标记。服务器中解析相应标记的函数同样用C语言来实现。运行时,当客户端发出查看某实时网页的请求后,嵌入式HTTP服务器将相应的网页文件从电子盘加载到内存进行逐项解析。当辨识出自定义标记后,就调用相应的函数。该函数返回该标记对应的当前值,并置换HTML文件流中的自定义标记。最后,嵌入式HTTP服务器将解析结果发送给客户端。实时网页的设计与相应的HTTP服务器处理程序得以分离,处于一种弱耦合关联状态。这样,网页界面的调整不会影响HTTP服务器的程序设计,HTTP服务器程序的修改也与网页界面设计无关,整个嵌入式HTTP服务器具备灵活性和可扩展性。
3.4 多线程
最初的进程定义包含程序、资源及其执行三部分,其中程序通常指代码,资源通常包括 内存资源、I/O资源、信号处理等,而程序的执行指执行上下文,这一部分后来发展为线程。在线程的概念出现以前,为了减小进程切换的开销,操作系统设计者逐渐修改正进程的概念,允许将进程所占有的资源从其主体剥离出来,允许某些进程共离享一部分资源,例如文件、信号、数据内存、甚至代码,这就是轻质进程的概念。Linux内核的2.0.x版本就已经实现了轻质进程。应用程序可以通过一个统一的clone()系统调用接口,用不同的参数指定创建轻质进程还是普通进程。在内核中,clone()调用经过参数传递和解释后会调用do_fork(),这个核内函数同时也是fork、vfork()系统调用的最终实现。在do_fork()中,不同的flone_flags将导致不同的行为。在LinuxThreads中,使用(CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND)参数调用clone()创建“线程”,表示共享内存、共享文件系统、共享文件描述符表,以及共享信号处理方式。Linux操作系统下,已经实现基于轻质进程的符号POSIX1003.C标准的线程库LinuxThreads。
在传统的Unix服务器程序设计中,为了使服务器具备并发处理连接的能力,通常采用父进程处理连接,并调用fork()创建子进程来处理用户请求的方法。这种方法的缺点是进程创建慢,耗费资源,进程切换开销大,进程之间通信比较困难等,不适用对资源、速度有要求的嵌入式系统。因此,在嵌入式HTTP服务器的开发中使用线程的方法。利用LinuxThreads提供的pthread_create()等函数派生出线程,也即轻质进程来处理多个HTTP请求。
4 工作流程和代码设计
4.1工作流程
嵌入式HTTP服务器程序开始运行时,主进程首先创建一个接口,并和主机地址绑定到一起,随后置为被动监听状态,等待客户端连接请求的到来。分别用函数socket()创建一个接口,bind()绑定地址,listen()监听,accept()接收来完成。当建立一个TCP连接后,函数accept()返回一个新的套接口描述符,主进程就创建一个新的子线程(轻质进程)处理这个新的连接。
子线程用于处理每具体的HTTP请求。子线程首先解析用户的HTTP请求。当用户请求一个网页时,子线程查找文件系统。如果该网页文件存在,且通过权限认证,就把它从CF卡读入内存并扫描,发现有自定义标记则调用相应函数进行处理,最后把结果返回给浏览器;否则给一个简单的出错消息。当用户是上传数据时,子线程调用相应函数读取数据进行处理,并返回处理结果给浏览器。
4.2 代码设计
在嵌入式HTTP服务器的代码设计中,考虑到代码的移植性和扩展性,利用C语言实现了面向对象风格的代码结构。代码主要由两上数据结构request_inf和response_inf以及其上一组操作函数组成。
结构request_inf和response_inf分别用来保存HTTP请求报文和响应报文的所有信息。在结构定义时,应根据具体应用特点设计结构包含的成分。
嵌入式HTTP服务器的函数包括通用函数、CGI函数和自定义标记处理函数等,其中通用函数是一些与HTTP1.1协议有关的函数。
(1)通用函数
*void prase_request_line(char *,struct *request_inf)
该函数用来解析HTTP请求报文的请求行(Request_Line),并把相应信息存放在结构request_inf中。其中,对请求行中URI部分的解析包括两种情况。如果用户请求一个网页,则获取文件路径、文件类型;如果用户要求上传数据,则把数据放在一个字符数组中。然后将文件路径和类型,或者指向该数组的指针、方法、版本号信息都放入结构request_inf中。
*void prease_general_header(char*,struct*request_inf)
该函数用来解析HTTP请求报文的调用首部(General_Header)。之所以把此函数与函数prase_request_line()分开,是考虑到程序的修植性和扩展性。请求行和通用首部是请求报文中的不同部分,不不同的场合下,要求解析的信息可能存在差导师。同时,这样也能使程序结构更清楚。比如,本项目要从通用首部解析字段Keep_Alive。该字段指明一个最长的时间或最大请求数目,在此范围内可以保持TCP连接不被释放(即前文提到的HTTP1.1的持续连接特性,persistent connection)。
*void prase_request_header(char*,struct*request_inf)
void prase_entity_header(char*,struct*request_inf)
HTTP请求报文的请求头部用来说明浏览器的一些信息,实体头部则用来说明请求报文中可能存在的实体主体信息。本项目实际上并不需要使用这两个函数来获取相关信息,但考虑到程序的扩展性和移植性,此处仍然把它列出来,它们是两个空函数。
*send_status_line(int fd,struct *response_inf)
此函数用来产生一个HTTP响应报文的状态行(Status_line)。状态行包括三部分内容,即HTTP版本、状态码以及解释状态码的简单短语。这些信息预先放在结构response_inf中。
*send_general_header(int fd,struct*response_inf)
send_response_header(int fd,struct*response_inf)
send_entity_header(int fd,struct*response_inf)
这三个函数分别用来产生HTTP响应报文的通用首部、响应首部(Response_header)和实体首部。嵌入式HTTP服务器是一个瘦服务器,功能非常简单。因此HTTP响应报文的通用首部、响应首部和实体首部中的可选字段许多是不需要的,还有许多是固定不变的,例如Last_modified和Content_type字段。Last_modified字段指出资源上次被修改的时间并由接收方解释。如果接收方已有此资源的拷贝,但此拷贝比Last-Modified域所指定的要旧,那该拷贝就是过期的。由于网页文件中含有自定义标记,具有实时性,所以此字段根本没有含有Content_type字段指出实体的媒体类型,本项目中的嵌入式HTTP服务器被设计成只支持HTML类型,因此该字段的内容总是Content_type=text/html。有关服务器和资源的所有标题域信息都被放入结构response_inf中。
*send_white_line(int fd)
此函数用于实体首部和实体之间传送一个空白行。
*void send_entity_body(int fd,char *buff_file)
此函数用来传递实体主体,实体主体实际上是一个处理后的网页文件,它被放在指针buff_file指向的缓冲区内。
*void zero_request_inf(struct*request_inf)
void zero_response_inf(struct*response_inf)
这两个函数用于结构request_inf和response_inf清零。
*void get_file(struct*request_inf,struct * response_inf,char*buff_file,void*,void*)
该函数用来处理用户HTTL请求。首先,函数会检查request_inf结构,判断用户是请求一个网页文件还是上传数据。当用户请求网页文件时,函数将根据request_inf结构中的文件路径信息,在文件系统录找此文件。如果文件不存在或不具备权限,则函数将状态码和解释短语写入结构response_inf,然后直接返回;否则读取文件并调用自定义标记处理函数,对标记进行处理,处理过的网页文件被放入buff_file指向的缓冲区内,并把状态码、解释短路和与实体有关的一些信息写入结构response_inf。当用户上传数据时,该函数调用CGI处理函数向CAN总线网络发送帧,然后将状态码和解释短路写入结构response_inf。利用状态码和解释短语只能用“200,OK”或“500,Internal Server Error”等,简单反映执行情况。用户要获取详细信息,可待一段合适的时间后请求网页文件。函数中两个void指针分别指向自定义标记处理函数和CGI处理函数,或者对应的函数指针数组。
(2)自定义标记处理函数和CGI处理函数
自定义标记处理函数用于对自定义的处理,每一类自定义标记对对应一种自定义标记处理函数,同一类自定义标记的不同数据点利用参数来区分,比如转子秤1的重量标记可以用weight1来表示。所有的自定义标记处理函数被放在一起,构成一个函数指针数组。自定义标记处理函数向CAN总线网络发送远程帧和接收数据帧,获取相应的状态信息。CGI总线网络发送远程帧和接收数据帧,获取相应的状态信息。CGI处理函数用变量名来区分,同一类变量对应一种CGI处理函数。与自定义标记处理函数类似,所有的CGI处理函数也被放在一起,构成一个函数指针数组。由于自定义标记函数和CGI处理函数类型众多,这里就不列举了。
结语
我们设计的嵌入式HTTP服务器具备良好的通用性和可移植性。通过更换或增加PC104通信模块,该服务器能够支持不同的现场总线,或同时连接几种不同的设备级轻质网络。同时在服务器代码设计中,用C语言实现了面向对象风格的代码结构。这样,如果要求服务器端具备更多的特性,只需要简单修改结构request_inf、response_inf、操作函数和网页文件即可达到目的。这种设计思路不仅适用于嵌入式HTTP服务器,随着硬件技术尤其是嵌入式操作系统技术的发展,它同样能够应用到其它嵌入式产品的开发中。
上一篇:广电安防监控系统中视频编解码卡的设计与实现
下一篇:一种边缘检测与扫描线相结合的车牌定位算法
推荐阅读最新更新时间:2024-03-30 21:31
技术文章—时效性网络(TSN)让工业控制如虎添翼
确定性是工业连接设计中的一个重要考量因素。工业控制和自动化应用需要以特定的时间间隔发送和接收数据,另外还需要以非常低的延迟提供有保证的数据。数据丢失(例如在关键的喷气推进系统中)会导致非常危险的后果。 IEEE 802.1 Ethernet是一种广泛部署的企业网络标准,其设计初衷并非为了满足工业应用的这种确定性要求。为实现确定性,工业连接器、电缆和控制器中仍然使用以太网的专属增强标准,如EtherCAT、PROFINET或SERCOS III,其结果是导致工业网络的标准混乱,各个部分无法互相通信。由于缺乏安全性和互操作性,这种四分五裂的网络在工业控制网络与工业物联网(IIoT)和工业4.0应用集成的过程中就成为了瓶颈。
[网络通信]
基于嵌入式技术的远程网络控制温控系统设计
文中将嵌入式控制技术与网络控制技术相结合,实现了基于 单片机 通过因特网的控制实现温控系统的设计,文中所采用的是 MSP 430F1 49单片机作为控制核心,MSP430F149微控制器控制以太网控制器CS8900A实现本地局域网的功能,通过TCP协议提供与因特网进行连接,可以实现对温箱的温度进行实时有效地控制。系统体积小巧,具备温度采集和远程控制功能和良好的可扩展性。 网络控制系统(NCSs)已经成为学术和工业领域的主要研究中心之一,随着日益增加的研究趋势和研究需要,能够成功应用最新的知识和信息则显得格外的重要。随着社会发展的需求,人们对温箱的应用和需求越来越广泛,在工业生产和日常生活或科学实验中,我们随处都可以看到温箱
[单片机]
基于ARM+uCLinux的网络控制系统设计与实现
引言 随着网络和通信技术的发展,嵌入式系统现已进入高速发展阶段。并在社会各个领域得到了广泛的应用。本文介绍了一种采用ARM+uCLinux作为开发平台。实现基于TCP/IP的远程系统监控.从而取代传统单片机 来实现数据采集、预处理和通信功能;并依靠互联网将数据向上位机传送,同时支持远端客户对设备进行远程控制,从而实现远程监控功能的具体方法。 1 系统平台的构建 本系统由嵌入式平台服务器 、前端控制器、前端传感器置PC来下载系统和应用软件。嵌入式系统平台能够收集现场数据。并传送到远端客户机,之后由远端客户机对数据进行处理,接着发送控制信号给系统服务器,以便通过前端控制器对设备进行远程控制。其系统结构如图1所示。
[单片机]
基于运行嵌入式Linux操作系统的ARM/DSP多机I2C通信设计方案
引言 在很多嵌入式控制系统中,系统既要完成大量的信息采集和复杂的算法,又要实现精确的控制功能。采用运行有嵌入式Linux操作系统的ARM9微控制器完成信号采集及实现上层控制算法,并向DSP芯片发送上层算法得到控制参数,DSP芯片根据获得的参数和下层控制算法实现精确、可靠的闭环控制。 1 多机系统组成 该多机控制系统以ARM9微控制器s3c2440为核心,采用I2C总线挂载多个DSP芯片TMS320F28015作为协控制器,构成整个控制系统的核心。 1.1 S3C2440及TMS320F28015简介 Samsung公司的处理器S3C2440是内部集成了ARM公司ARM920T处理器内核的32位微控制器,资源
[单片机]
微软与5家Android及Linux用户签署授权协议
微软宣布再与5家企业签署exFAT(Extended File Allocation Table)档案系统技术的专利授权协议,这5家企业为Sharp、Sigma、NextoDi、Black Magic及Atomos Global,多是因使用了Android或Linux平台才与微软签署授权协议。 相关的授权协议涵盖了Sharp所开发的Android平板电脑,Sigma与NextoDi所设计的数码相机与配件,以及Black Magic与Atomos Global所打造的广播录影设备。 exFAT为微软专为快闪磁盘所设计的档案管理系统,可处理快闪记忆体装置中比FAT高上5倍的档案容量,并改善了档案存取速度,除了有利于今日高容量的多媒
[网络通信]
在MIPS开发板上建立Linux系统及开发环境
作者Email: jie_yi@sohu.com
介绍了利用已有的MIPS版Linux源文件包,编译可运行的Linux内核的方式;讨论了在主机上建立相关服务器,通过NFS服务从主机上下载内核,在无盘开发板上启动Linux的方法。
关键词:MIPS NFS 启动Linux
一、引言
大多数基于MIPS处理器的平台上都没有提供软、硬盘接口,一般情况下,也没有在板载Flash里烧入可使用的操作系统。没有操作系统,用户的使用就会受到很多限制,应用程序的开发、调试过程就会变得相当复杂。因此,建立合适的操作系统及开发环境,可以方便用户,简化开发调试过程。本文以RedHat Linux 为例,说明在RM7000A处理器无盘
[嵌入式]
焦炉集气管压力模糊神经网络控制系统
摘要:针对焦炉集气管压力这类多变量非线性系统,提出一种基于模糊神经网络的智能协调控制方案。应用遗传算法对模糊神经网络结构和参数进行优化,并采用PLC的逻辑梯形图语言编程实现智能协调运算。工程应用表明了系统设计的有效性。
关键词:可编程控制器 模糊神经网络 智能控制
焦炉集气管压力控制是焦炉控制的关键之一。压力大时焦炉冒烟严重,近距离不能看清设备,大量焦炉媒气进入空气中,污染环境;压力小时空气吸入严重,影响焦炉寿命和焦炉煤气质量。因此,采用先进控制手段,对焦炉焦气管压力进行长期稳定控制,对于改善环境、提高煤气回收量和质量、提高焦炉辅助产品产量和质量,具有重要的意义。焦炉集气管控制系统的主要问题有:
(1)焦炉集气管压力系统是一
[应用]
小广播
热门活动
换一批
更多
最新工业控制文章
更多精选电路图
更多热门文章
更多每日新闻
- Allegro MicroSystems 在 2024 年德国慕尼黑电子展上推出先进的磁性和电感式位置感测解决方案
- 左手车钥匙,右手活体检测雷达,UWB上车势在必行!
- 狂飙十年,国产CIS挤上牌桌
- 神盾短刀电池+雷神EM-i超级电混,吉利新能源甩出了两张“王炸”
- 浅谈功能安全之故障(fault),错误(error),失效(failure)
- 智能汽车2.0周期,这几大核心产业链迎来重大机会!
- 美日研发新型电池,宁德时代面临挑战?中国新能源电池产业如何应对?
- Rambus推出业界首款HBM 4控制器IP:背后有哪些技术细节?
- 村田推出高精度汽车用6轴惯性传感器
- 福特获得预充电报警专利 有助于节约成本和应对紧急情况
更多往期活动
11月16日历史上的今天
厂商技术中心