如何开发自己的HttpServer-NanoHttpd源码解读

如何开发自己的HttpServer-NanoHttpd源码解读,第1张

现在作为一个开发人员,http server相关的内容已经是无论如何都要了解的知识了。用curl发一个请求,配置一下apache,部署一个web server对我们来说都不是很难,但要想搞清楚这些背后都发生了什么技术细节还真不是很简单的。所以新的系列将是分享我学习Http Server的过程。

NanoHttpd是Github上的一个开源项目,号称只用一个java文件就能创建一个http server,我将通过分析NanoHttpd的源码解析如何开发自己的HttpServer。Github 地址:https://githubcom/NanoHttpd/nanohttpd

在开始前首先简单说明HttpServer的基本要素:

1能接受HttpRequest并返回HttpResponse

2满足一个Server的基本特征,能够长时间运行

关于Http协议一般HttpServer都会声明支持Http协议的哪些特性,nanohttpd作为一个轻量级的httpserver只实现了最简单、最常用的功能,不过我们依然可以从中学习很多。

首先看下NanoHttpd类的start函数

[java] view plaincopy

public void start() throws IOException {  

        myServerSocket = new ServerSocket();  

        myServerSocketbind((hostname != null)  new InetSocketAddress(hostname, myPort) : new InetSocketAddress(myPort));  

  

        myThread = new Thread(new Runnable() {  

            @Override  

            public void run() {  

                do {  

                    try {  

                        final Socket finalAccept = myServerSocketaccept();  

                        registerConnection(finalAccept);  

                        finalAcceptsetSoTimeout(SOCKET_READ_TIMEOUT);  

                        final InputStream inputStream = finalAcceptgetInputStream();  

                        asyncRunnerexec(new Runnable() {  

                            @Override  

                            public void run() {  

                                OutputStream outputStream = null;  

                                try {  

                                    outputStream = finalAcceptgetOutputStream();  

                                    TempFileManager tempFileManager = tempFileManagerFactorycreate();  

                                    HTTPSession session = new HTTPSession(tempFileManager, inputStream, outputStream, finalAcceptgetInetAddress());  

                                    while (!finalAcceptisClosed()) {  

                                        sessionexecute();  

                                    }  

                                } catch (Exception e) {  

                                    // When the socket is closed by the client, we throw our own SocketException  

                                    // to break the  "keep alive" loop above  

                                    if (!(e instanceof SocketException && "NanoHttpd Shutdown"equals(egetMessage()))) {  

                                        eprintStackTrace();  

                                    }  

                                } finally {  

                                    safeClose(outputStream);  

                                    safeClose(inputStream);  

                                    safeClose(finalAccept);  

                                    unRegisterConnection(finalAccept);  

                                }  

                            }  

                        });  

                    } catch (IOException e) {  

                    }  

                } while (!myServerSocketisClosed());  

            }  

        });  

        myThreadsetDaemon(true);  

        myThreadsetName("NanoHttpd Main Listener");  

        myThreadstart();  

    }  

1创建ServerSocket,bind制定端口

2创建主线程,主线程负责和client建立连接

3建立连接后会生成一个runnable对象放入asyncRunner中,asyncRunnerexec会创建一个线程来处理新生成的连接。

4新线程首先创建了一个HttpSession,然后while(true)的执行httpSessionexec。

这里介绍下HttpSession的概念,HttpSession是java里Session概念的实现,简单来说一个Session就是一次httpClient->httpServer的连接,当连接close后session就结束了,如果没结束则session会一直存在。这点从这里的代码也能看到:如果socket不close或者exec没有抛出异常(异常有可能是client段断开连接)session会一直执行exec方法。

一个HttpSession中存储了一次网络连接中server应该保存的信息,比如:URI,METHOD,PARAMS,HEADERS,COOKIES等。

5这里accept一个client的socket就创建一个独立线程的server模型是ThreadServer模型,特点是一个connection就会创建一个thread,是比较简单、常见的socket server实现。缺点是在同时处理大量连接时线程切换需要消耗大量的资源,如果有兴趣可以了解更加高效的NIO实现方式。

当获得client的socket后自然要开始处理client发送的httprequest。

Http Request Header的parse:

[plain] view plaincopy

// Read the first 8192 bytes  

// The full header should fit in here  

                // Apache's default header limit is 8KB  

                // Do NOT assume that a single read will get the entire header at once!  

                byte[] buf = new byte[BUFSIZE];  

                splitbyte = 0;  

                rlen = 0;  

                {  

                    int read = -1;  

                    try {  

                        read = inputStreamread(buf, 0, BUFSIZE);  

                    } catch (Exception e) {  

                        safeClose(inputStream);  

                        safeClose(outputStream);  

                        throw new SocketException("NanoHttpd Shutdown");  

                    }  

                    if (read == -1) {  

                        // socket was been closed  

                        safeClose(inputStream);  

                        safeClose(outputStream);  

                        throw new SocketException("NanoHttpd Shutdown");  

                    }  

                    while (read > 0) {  

                        rlen += read;  

                        splitbyte = findHeaderEnd(buf, rlen);  

                        if (splitbyte > 0)  

                            break;  

                        read = inputStreamread(buf, rlen, BUFSIZE - rlen);  

                    }  

                }  

1读取socket数据流的前8192个字节,因为http协议中头部最长为8192

2通过findHeaderEnd函数找到header数据的截止位置,并把位置保存到splitbyte内。

[java] view plaincopy

if (splitbyte < rlen) {  

                    inputStreamunread(buf, splitbyte, rlen - splitbyte);  

                }  

  

                parms = new HashMap<String, String>();  

                if(null == headers) {  

                    headers = new HashMap<String, String>();  

                }  

  

                // Create a BufferedReader for parsing the header  

                BufferedReader hin = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(buf, 0, rlen)));  

  

                // Decode the header into parms and header java properties  

                Map<String, String> pre = new HashMap<String, String>();  

                decodeHeader(hin, pre, parms, headers);  

1使用unread函数将之前读出来的body pushback回去,这里使用了pushbackstream,用法比较巧妙,因为一旦读到了header的尾部就需要进入下面的逻辑来判断是否需要再读下去了,而不应该一直读,读到没有数据为止

2decodeHeader,将byte的header转换为java对象

 

1Http协议第一行是Method URI HTTP_VERSION

2后面每行都是KEY:VALUE格式的header

3uri需要经过URIDecode处理后才能使用

4uri中如果包含?则表示有param,httprequest的param一般表现为:/indexjspusername=xiaoming&id=2

下面是处理cookie,不过这里cookie的实现较为简单,所以跳过。之后是serve方法,serve方法提供了用户自己实现httpserver具体逻辑的很好接口。在NanoHttpd中的serve方法实现了一个默认的简单处理功能。

 

这个默认的方法处理了PUT和POST方法,如果不是就返回默认的返回值。

parseBody方法中使用了tmpFile的方法保存httpRequest的content信息,然后处理,具体逻辑就不细说了,不是一个典型的实现。

最后看一下发response的逻辑:

                    sendAsFixedLength(outputStream, pending);  

                }  

                outputStreamflush();  

                safeClose(data);  

            } catch (IOException ioe) {  

                // Couldn't write No can do  

            }  

        }  

发送response的步骤如下:

1设置mimeType和Time等内容。

2创建一个PrintWriter,按照HTTP协议依次开始写入内容

3第一行是HTTP的返回码

4然后是content-Type

5然后是Date时间

6之后是其他的HTTP Header

7设置Keep-Alive的Header,Keep-Alive是Http11的新特性,作用是让客户端和服务器端之间保持一个长链接。

8如果客户端指定了ChunkedEncoding则分块发送response,Chunked Encoding是Http11的又一新特性。一般在response的body比较大的时候使用,server端会首先发送response的HEADER,然后分块发送response的body,每个分块都由chunk length\r\n和chunk data\r\n组成,最后由一个0\r\n结束。

 

9如果没指定ChunkedEncoding则需要指定Content-Length来让客户端指定response的body的size,然后再一直写body直到写完为止。

 

最后总结下实现HttpServer最重要的几个部分:

1能够accept tcp连接并从socket中读取request数据

2把request的比特流转换成request对象中的对象数据

3根据http协议的规范处理http request

4产生http response再写回到socket中传给client。

随着互联网的发展,越来越多的人开始关注自己的个人网站,而搭建一个个人网站的第一步就是选择一个合适的web服务器软件。在这篇文章中,我们将介绍如何选择和使用个人web服务器软件来搭建自己的网站。

一、选择个人web服务器软件

在选择个人web服务器软件时,需要考虑以下几个方面:

1操作系统:不同的web服务器软件适用于不同的操作系统,例如,Apache适用于Linux和Windows系统,IIS适用于Windows系统。

2功能需求:不同的web服务器软件提供不同的功能,例如,Apache提供了丰富的模块和插件,可以满足各种需求;Nginx则提供了高性能的反向代理和负载均衡功能。

3安全性:web服务器软件的安全性非常重要,因为它们是公开的,并且可能面临各种攻击。因此,选择一个安全性好的web服务器软件非常重要。

基于以上考虑,我们推荐使用Apache或Nginx作为个人web服务器软件。

二、安装和配置个人web服务器软件

1安装Apache

在Linux系统上,可以使用以下命令安装Apache:

sudoapt-getinstallapache2

在Windows系统上,可以从Apache官网下载安装程序进行安装。

2配置Apache

在Linux系统上,可以使用以下命令打开Apache配置文件:

sudonano/etc/apache2/apache2conf

在Windows系统上,可以在安装目录下找到httpdconf文件进行编辑。

在Apache配置文件中,可以设置服务器的一些基本信息,例如监听端口、虚拟主机等等。此外,还可以配置Apache模块和插件,以满足不同的需求。

3安装Nginx

在Linux系统上,可以使用以下命令安装Nginx:

sudoapt-getinstallnginx

在Windows系统上,可以从Nginx官网下载安装程序进行安装。

4配置Nginx

在Linux系统上,可以使用以下命令打开Nginx配置文件:

sudonano/etc/nginx/nginxconf

在Windows系统上,可以在安装目录下找到nginxconf文件进行编辑。

在Nginx配置文件中,可以设置服务器的一些基本信息,例如监听端口、虚拟主机等等。此外,还可以配置Nginx模块和插件,以满足不同的需求。

三、搭建个人网站

在安装和配置个人web服务器软件之后,就可以开始搭建个人网站了。具体步骤如下:

1创建网站目录

在服务器上创建一个网站目录,用于存放网站文件。可以使用以下命令在Linux系统上创建一个网站目录:

sudomkdir/var/www/mywebsite

在Windows系统上,可以在安装目录下创建一个网站目录。

2编写网站文件

在网站目录下创建一个indexhtml文件,用于展示网站内容。可以使用以下命令在Linux系统上创建一个indexhtml文件:

sudonano/var/www/mywebsite/indexhtml

在Windows系统上,可以使用任何文本编辑器创建一个indexhtml文件。

3配置虚拟主机

在Apache或Nginx配置文件中,配置一个虚拟主机,将网站目录与域名绑定。例如,在Apache配置文件中,可以添加以下代码:

ServerNamemywebsitecom

DocumentRoot/var/www/mywebsite

在Nginx配置文件中,可以添加以下代码:

server{

listen80;

server_namemywebsitecom;

root/var/www/mywebsite;

}

4启动服务器

在完成以上步骤后,就可以启动web服务器,访问自己的网站了。可以使用以下命令在Linux系统上启动Apache或Nginx:

sudoserviceapache2start

sudoservicenginxstart

在Windows系统上,可以在服务管理器中启动Apache或Nginx服务。

如何把本地电脑做成服务器

由于现在宽带速度已经很快,电脑配置也越来越高,所以可以把自用PC电脑作为互联网网站服务器,首先需要分清宽带IP和本机IP是有区别的,演示的1921681134是本机IP,另外一个地址是宽带IP地址。步骤如下:

1、首先本地电脑要搭建好内网能访问的服务器,本地电脑搭建网站的教程很多,本步骤省略,用本地IP能访问的的服务器,在地址栏中输入本机IP地址1921681134访问自己的电脑网站;

2、如何让外网能访问,打开路由器设定;

3、进入转发规则-虚拟服务器-添加新条目;

4、如图输入,根据自己的本机IP进行输入,保存;

5、现在用固定宽带IP已经能外网访问了;

6、本地电脑的宽带IP地址,可以百度查询;

7、如何通过本地的域名也能外网访问呢,进去域名管理后台,将域名解析A记录指向本地的宽带IP地址;

8、现在,地址栏输入本地的域名可以访问了;

如何在自己的电脑上搭建服务器环境?

你要是测试php的话,就不能安装iis,因为你要测试php,需要安装apache服务器,iis和apache服务器都是提供的一种功能,都占用80端口,顶以只能安装一个!

WAMP5和xampp 都是windows下面架设php+apache+mysql的集成环境软件,你可以任选一个,在google里面找找,很多人使用的,再找找帮助,如果看不懂,请找视频教程,对一个初学者来说,视频教程可能容易接受一些!

/

lz不明白呀!下载WAMP5和xampp这两个里面的其中一个,下载完安装上就行了!这两个软件是php集成开发环境,安装完这个软件之后,就等于你安装完php+apache+mysql了!

做网站怎么设置本地服务器?

我用的是“asp代码调试工具”。

其实这个不到一兆的软件已经十分够用,除礌你有什么非常特别的需求,比如说iis专业的组件,否则这个软件已经全部可以胜任。

我是Ghostxp系统,IIS从来都装不上。每次都是用这个

我使用的是2个版本,

一个是“asp代码调试工具”,测试打开的网址是 99端口。

第二个是“网站调试工具”,端口是默认80如果80被占用,那么就随机开启一个端口。

其实也都是netbox核心的。

除了某些高级函数,比如 responsechaset sessionchaset 用不上以为其他根本和IIS没什么两样,

如何在本地搭建一个服务器,可以外网访问的 5分

路由器上,将8888端口映射到服务器ip的8888端口,你差了这一步。 如果不会,直接将服务器ip添加到dmz中也行。

如何在本地搭建服务器

可以使用IIS搭建服务器或者用Apache

如何在本地搭建服务器环境和数据库

1、假设论坛服务器在自己的计算机安装服务器操作系统如win2003 win2008 等。

2、配置服务器,并安装asp所需对应服务。如打开IIS服务,安装SQL Server 2005 ,Microsoft Visual Studio 2005等软件。

3、软件环境好了,接下来看你的上网方式。稳定的服务器一般使用静态IP地址和带宽,选择所在地区最好的出口,但这成本对于个人比较高。家庭用户动态IP地址则受网络运营商限制,不一定能做服务器使用(比如我们这就是,在电信网通都封掉了动态IP做服务器的可能性,不在同一个城市,根本访问不了)。动态IP可以通过动态域名解释软件如花生壳之类的,来绑定域名。当然,也可以通过直接访问IP地址来访问。

4、如果家里边使用路由,要在自己的路由上边设置端口映射。

如何在本地搭建IIS服务器

安装WINSOWS2000自带的IIS作为服务器。(WINSOWS98的PWS也可以,但是不推荐,安装大致和2000相同,这里就不详细说了。)

先是控制面板-添加或删除程序。

然后是添加删除windows组件-选中IIS组件前面的勾

装好以后打开控制面板中的管理工具,会发现多了两个图标,打开IIS管理器

选择默认WEB站点,然后右键属性或者直接按快捷键

如何建立本地sql服务器

你运行的Management Studio是管理工具(不是sqlserver服务器),是用来管理服务器的,新建服务器注册,就是连接到一个新的sqlserver服务器上。

要连接本机的sqlserver服务,请使用(local)或者是127001,集成验证方式。

SQLServer在一台机器上是可以安装多个相互独立的服务(实例),用不同的实例名区分,但是一般不这么干,单独的服务一般就能满足需求了。

1、安装sqlserver,一般用默认实例名,并将当前用户添加为数据库管理员,安装过程中会让你设置验证方式(集成验证还是混合验证),如果你的程序使用用户名密码连接sql,则需要启用混合验证(并需要设置sa密码)

2、安装完成后(需重启),启动Management Studio连接本地数据库服务,连接后可以新建数据库,数据表(当然,你也可以用程序连接后用代码创建)

3、Management Studio 连接服务器时,和程序连接服务器一样,如果连接的SQLSERVER不是服务器上的默认实例名,则服务器地址后需要有实例名(形如:1921680100\SQLEXPRESS),如果省略实例名则连接默认实例(默认实例名MSSQLSERVER)

如何在 android 本地搭建一个 服务器

在Android假设服务器,其最终的结果就是根据预先设定好的端口和Url访问到你预先放好的资源。

步骤简单的概括几部就是

1,实现NanoHttpd类

2,设置端口和路径

3,访问实验。

blogcsdn/676835

如何在本地搭建一个ftp服务器

安装FTP服务

开始--》管理工具--》服务器管理器

安装IIS/FTP角色

打开服务器管理器,找到添加角色,然后点击,弹出添加角色对话框,选择下一步

选择Web服务器(IIS),然后选择FTP服务,直到安装完成。

在IIS中查看,如果能够右键创建FTP站点,则表明FTP服务安装成功

创建Windows用户名和密码,用于FTP使用。

开始--》管理工具--》服务器管理器,添加用户,如下图:本实例使用ftptest

在服务器磁盘上创建一个供FTP使用的文件夹,创建FTP站点,指定刚刚创建的用户FtpTest,赋予读写权限

客户端测试。直接使用ftp:服务器ip地址:ftp端口,如图。弹出输入用户名和密码的对话框表示配置成功,正确的输入用户名和密码后,即可对FTP文件进行相应权限的操作。

将视频从MP4文件切片成多个ts文件,并使用AES-128对每一片视频进行加密,最后生成m3u8文件

视频加密参考: https://wwwcnblogscom/codeAB/p/9184266html

举个例子

对于Android手机是不能直接播放的,必须要搭建服务器,使用Ubuntu搭建服务器请参考 网络直播/点播服务器搭建

这里主要讲解如何在Android手机上搭建m3u8视频服务器, NanoHTTPD 可以轻松搭建WebServer。

本地播放参考 https://giteecom/2021/LPlayer

开启服务

关闭服务

服务器请求链接说明

最后提供一个 单java文件的NanoHTTPD ,简单,高效,赞一个

DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
网站模板库 » 如何开发自己的HttpServer-NanoHttpd源码解读

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情