Simple webserver with nanohttpd

Source: Internet
Author: User
Tags keep alive

0x00

Before introducing the use of NANOHTTPD to implement simple webserver, we first familiar with the next LAN socket communication. A client project with a code address of https://github.com/jltxgcy/AppVulnerability/tree/master/MyClient. A server project with a code address of https://github.com/jltxgcy/AppVulnerability/tree/master/MyServer.

Two projects to the same WiFi environment, myclient project to modify the connection target IP address. As follows:

Clientsocket = new Socket ("10.10.154.74", 6100);
This IP address can be obtained by setting the->ip address of the status information, such as the phone. Such as:


The specific code is not introduced, we analyze.


0x01

The following describes the use of nanohttpd for simple webserver. The code address is Https://github.com/jltxgcy/AppVulnerability/tree/master/NanoHttpD.

After running NANOHTTPD, the native UC browser enters http://127.0.0.1:8088 and returns it works. It works also occurs when you enter http://10.10.154.12 (that is, the mobile IP that runs NANOHTTPD) on other mobile browsers that connect to the same wifi.

So what is the principle of this local webserver?

Let's look at the main activity first, the code is as follows:

public class Mainactivity extends Activity {private simpleserver server; @Overrideprotected void OnCreate (Bundle Savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (r.layout.activity_main); server = new Simpleserver (); try {//Because the program simulates HTML placement in the asset directory,//So store the Assetmanager pointer here. Server.asset_mgr = This.getassets ();//Start Web Service Server.start (); LOG.I ("Httpd", "the server started."); catch (IOException IoE) {    LOG.W ("Httpd", "The server could not start.");}}       ......}
The Simpleserver object is created, and then its Start method is called. Let's look at the code for the Simpleserver class:

public class Simpleserver extends nanohttpd {Assetmanager asset_mgr;    The public simpleserver () {///port is 8088, which means to visit http://127.0.0.1:8088 via the "Super" (8088); } Public Response serve (String uri, method, Map<string, string> header, Map<stri  Ng, string> parameters, map<string, string> files) {int len = 0; byte[] buffer = NULL;    LOG.D ("Jltxgcy", Header.get ("remote-addr"));        The default incoming URL starts with "/" and needs to be removed, otherwise it becomes an absolute path String file_name = uri.substring (1);    The default page name is set to Index.html if (File_name.equalsignorecase ("")) {file_name = "index.html"; } try {//Assetmanager directly open file for read operation InputStream in = Asset_mgr.open (file_name, assetmanager.access_buffer);//Assuming a single Web page text           The upper limit of the size of the piece is 1MB buffer = new byte[1024*1024];        int temp=0;              while ((Temp=in.read ())!=-1) {buffer[len]= (byte) temp;          len++;  } in.close (); } catch (IOException e) {//TODO auto-generated catch blocke.printstAcktrace ();}    Returns the contents of the read file to the browser return new Nanohttpd.response (Buffer,0,len); }}
Simpleserver inherits the Start method that Nanohttpd,server.start () actually calls the NANOHTTPD class. As follows:

public void Start () throws IOException {myserversocket = new ServerSocket ();        Myserversocket.bind ((hostname! = null)? New Inetsocketaddress (hostname, myport): New Inetsocketaddress (MyPort));                    MyThread = new Thread (new Runnable () {@Override public void run () {do {                        try {final Socket finalaccept = Myserversocket.accept ();                        Registerconnection (finalaccept);                        Finalaccept.setsotimeout (socket_read_timeout);                        Final InputStream InputStream = Finalaccept.getinputstream ();                            if (InputStream = = null) {safeclose (finalaccept);                        Unregisterconnection (finalaccept);                                } else {asyncrunner.exec (new Runnable () {@Override                 public void Run () {                   OutputStream outputstream = null;                                        try {outputstream = Finalaccept.getoutputstream ();                                        Tempfilemanager Tempfilemanager = Tempfilemanagerfactory.create ();                                        HTTPSession session = new HTTPSession (Tempfilemanager, InputStream, OutputStream, finalaccept.getinetaddress ()); while (!finalaccept.isclosed ()) {Session.execut                                        E (); }} 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 (E.getmessage ()))){E.printstacktrace ();                                        }} finally {Safeclose (outputstream);                                        Safeclose (InputStream);                                        Safeclose (finalaccept);                                    Unregisterconnection (finalaccept);                        }                                }                            });            }} catch (IOException e) {}} while (!myserversocket.isclosed ());        }        });        Mythread.setdaemon (TRUE);        Mythread.setname ("nanohttpd Main Listener");    Mythread.start (); }
A socket Server was created,myserversocket.accept () blockingWait for the connection, when the native browser entershttp://127.0.0.1:8088, the connection is established, then the connection is processed, and the mythread thread continues to execute to Session.execute. Let's look at the code for this function:

@Override public void Execute () throws IOException {try {//Read the first 8192 bytes.                The full header is should fit in here.                Apache ' s default header limit is 8KB.                Do not assume, a single read would get the entire header at once!                byte[] buf = new Byte[bufsize];                Splitbyte = 0;                Rlen = 0;                    {int read =-1;                    try {read = Inputstream.read (buf, 0, BUFSIZE);                        } catch (Exception e) {safeclose (InputStream);                        Safeclose (OutputStream);                    throw new SocketException ("nanohttpd Shutdown"); } if (read = =-1) {//socket was been closed safeclose (i                        Nputstream);                        Safeclose (OutputStream); Throw new SocketException ("nanohttpd Shutdown");                        } while (Read > 0) {rlen + = read;                        Splitbyte = Findheaderend (buf, Rlen);                        if (Splitbyte > 0) break;                    Read = Inputstream.read (buf, Rlen, Bufsize-rlen); }} if (Splitbyte < Rlen) {Bytearrayinputstream Splitinputstream = NE                    W Bytearrayinputstream (buf, Splitbyte, rlen-splitbyte);                    Sequenceinputstream Sequenceinputstream = new Sequenceinputstream (Splitinputstream, InputStream);                InputStream = Sequenceinputstream;                } 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 Hashma                P<string, string> ();                Decodeheader (Hin, Pre, parms, headers);                method = Method.lookup (Pre.get ("method")); if (method = = null) {throw new Responseexception (Response.Status.BAD_REQUEST, "Bad Request:syntax err                Or. ");}                URI = Pre.get ("uri");                cookies = new Cookiehandler (headers);                Ok, now does the serve () Response R = Serve (this); if (r = = null) {throw new Responseexception (Response.Status.INTERNAL_ERROR, "SERVER INTERNAL error:se Rve () returned a null response. ");                    else {cookies.unloadqueue (R); R.setrequestmethod (method);                R.send (OutputStream);                }} catch (SocketException e) {//Throw it out to close socket object (finalaccept)            Throw e;            } catch (Sockettimeoutexception ste) {throw Ste; } catch (IOException IoE) {Response r = new Response (Response.Status.INTERNAL_ERROR, Mime_plaintext, "SERV                ER INTERNAL error:ioexception: "+ ioe.getmessage ());                R.send (OutputStream);            Safeclose (OutputStream); } catch (Responseexception re) {Response r = new Response (Re.getstatus (), Mime_plaintext, Re.getmessage ())                ;                R.send (OutputStream);            Safeclose (OutputStream);            } finally {tempfilemanager.clear (); }        }
This function parseshttp://127.0.0.1:8088, and then calls the Simpleserver serve method, which returns the content that is displayed in the browser.

We look at the public Response serve (String uri, method, Map<string, string> header, Map<string, String> PA, depending on the debug) Rameters, map<string, string> files), what are the values returned by these parameters?

The URL is/,method to Get,head for {ACCEPT=TEXT/HTML,APPLICATION/XHTML+XML,APPLICATION/XML;Q=0.9,*/*;Q=0.8,UC/145,PLUGIN/1, Alipay/un, Accept-encoding=gzip, host=127.0.0.1:8088, ACCEPT-LANGUAGE=ZH-CN, http-client-ip=127.0.0.1, Cache-control=max-age=0, X-UCBROWSER-UA=DV (Nexus 6);p R (ucbrowser/10.7.0.634), ov (Android 5.1.1), SS (411*683);p I ( 1440*2392), Bt (UM);p m (1), BV (1), NM (0); im (0); Sr (0); NT (2);, remote-addr=127.0.0.1, user-agent=mozilla/5.0 (Linux; U Android 5.1.1; ZH-CN; Nexus 6 build/lmy47z) applewebkit/534.30 (khtml, like Gecko) version/4.0 ucbrowser/10.7.0.634 u3/0.8.0 Mobile safari/534. The connection=keep-alive},parameters is {nanohttpd.query_string=null},files {}.


If the requested address is http://127.0.0.1:8088/adv?d=1, the URL is adv,parameter {d=1, nanohttpd.query_string=d=1}.

Use nanohttpd for simple webserver

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.