I recently came across this idea of creating a web server. And surprisingly it is not as bad as it seems to be. I chose java for implementing it cause it was the easiest. A web server is a software that runs on your computer (the server), and it acts as a server that sends web pages from your computer to another when asked for. The most simplest way of knowing this is to build one. Lets quickly build a server that outputs date on your browser for an instance.
Now that it is simple to create it in Java, why not android. Open up eclipse and set this layout
And Update strings.xml to add the "Run Server" to strings.xml, this is not necessary but a good android programming practice to include all the strings in the xml files and nothing in the program itself.
And update the manifest to include android:permission:INTERNET
In the main WebServer.java file use this code
As you can clearly see my computer connected to the usb internet of my phone is broadcasting at http://192.168.42.129
Similarly find out yours and then open up browser and type in the ip followed by the port 1234. In my case it is http://192.168.42.129:1234/ and we get this
The program may report that the activity encountered unexpected error. Giving you the option to either "Force close" or "Wait". This happens because the activity is struck int the while(true) loop and is not responding to create changes in activity. Select "wait" until you want the server running. The solution to avoid this is to create a background process that runs asynchronously, and finishes the job. Try doing this google Async task android.
But http isn't this simple. It is standardized to have some protocols in it that has to be adhered to. Firstly Browser must send some message so that the server will know what it wants. Let us adjust the last program to get this message.
- import java.net.*;
- import java.io.*;
- public class Server {
- public static void main(String[] args)
- {
- try
- {
- //Create a socket at port 80. The port over which browser usually connects
- ServerSocket sock = new ServerSocket(80);
- //Go into a loop and wait for connections to occur
- while(true)
- {
- //Accept a connection
- Socket client = sock.accept();
- //set PrintWriter to the output stream of the connected client
- PrintWriter pout = new PrintWriter(client.getOutputStream(), true);
- //Print date from java.util to the client's output stream
- pout.println(new java.util.Date().toString());
- //Close the connection with the client
- client.close();
- }
- }
- catch (Exception ioe)
- {
- //In case of exceptions print it to the console.
- System.out.println(ioe);
- }
- }
- }
This is a very simple program that does nothing but print date on the screen of the browser. Compile it
javac Server.java (Both Windows and Linux)
And run it
java Server (Both Windows and Linux)
Now open your browser and type in http://localhost/ or http://127.0.0.1/ and if everything has gone fine then voila.
Now that it is simple to create it in Java, why not android. Open up eclipse and set this layout
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
- <Button
- android:id="@+id/button1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_centerHorizontal="true"
- android:text="@string/runserver" />
- <TextView
- android:id="@+id/textView1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_above="@+id/button1"
- android:layout_alignParentLeft="true"
- android:layout_alignParentRight="true"
- android:layout_alignParentTop="true"/>
- </RelativeLayout>
And Update strings.xml to add the "Run Server" to strings.xml, this is not necessary but a good android programming practice to include all the strings in the xml files and nothing in the program itself.
- <resources>
- <string name="app_name">WebServer</string>
- <string name="menu_settings">Settings</string>
- <string name="runserver">Run Server</string><string name="title_activity_main">WebServer</string>
- </resources>
And update the manifest to include android:permission:INTERNET
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.regnartstranger.webserver"
- android:versionCode="1"
- android:versionName="1.0" >
- <uses-sdk
- android:minSdkVersion="10"
- android:targetSdkVersion="15" />
- <uses-permission android:name="android.permission.INTERNET" />
- <application
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name"
- android:theme="@style/AppTheme" >
- <activity
- android:name=".WebServer"
- android:label="@string/title_activity_main" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
- </manifest>
In the main WebServer.java file use this code
- package com.regnartstranger.webserver;
- import android.os.Bundle;
- import android.app.Activity;
- import android.view.Menu;
- import android.view.View;
- import android.widget.Button;
- import android.widget.TextView;
- import java.net.*;
- import java.io.*;
- public class WebServer extends Activity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- Button runserver = (Button)findViewById(R.id.button1);
- runserver.setOnClickListener((android.view.View.OnClickListener) new Server());
- }
- public class Server implements android.view.View.OnClickListener {
- public void onClick(View clickedButton) {
- TextView textMsg = (TextView)findViewById(R.id.textView1);
- try{
- while(true){
- ServerSocket socket = new ServerSocket(1234);
- Socket client = socket.accept();
- PrintWriter pout = new PrintWriter(client.getOutputStream(), true);
- pout.println("Android Webserver");
- client.close();
- socket.close();
- }
- }
- catch(Exception ioe)
- {
- System.err.print(ioe);
- textMsg.append("Error: " + ioe.getMessage() + "\n" + "Desc: " + ioe.getLocalizedMessage() + "\n");
- }
- }
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.activity_main, menu);
- return true;
- }
- }
Now compile and load the program into your phone. Connect your computer to the phone's internet connection. And open the browser. Now to find out which ip the phone is broadcasting open up abd shell and type netcfg. This should display up the broadcast address of the server.
As you can clearly see my computer connected to the usb internet of my phone is broadcasting at http://192.168.42.129
Similarly find out yours and then open up browser and type in the ip followed by the port 1234. In my case it is http://192.168.42.129:1234/ and we get this
The program may report that the activity encountered unexpected error. Giving you the option to either "Force close" or "Wait". This happens because the activity is struck int the while(true) loop and is not responding to create changes in activity. Select "wait" until you want the server running. The solution to avoid this is to create a background process that runs asynchronously, and finishes the job. Try doing this google Async task android.
But http isn't this simple. It is standardized to have some protocols in it that has to be adhered to. Firstly Browser must send some message so that the server will know what it wants. Let us adjust the last program to get this message.
- import java.net.*;
- import java.io.*;
- public class Server {
- public static void main(String[] args)
- {
- try
- {
- //Create a socket at port 80. The port over which browser usually connects
- ServerSocket sock = new ServerSocket(80);
- //Go into a loop and wait for connections to occur
- while(true)
- {
- //Accept a connection
- Socket client = sock.accept();
- //Create a buffer to read the client request
- BufferedReader input = new BufferedReader(new InputStreamReader(client.getInputStream()));
- //Print out the requested line
- System.out.println(input.readLine());
- //set PrintWriter to the output stream of the connected client
- PrintWriter pout = new PrintWriter(client.getOutputStream(), true);
- //Print date from java.util to the client's output stream
- pout.println(new java.util.Date().toString());
- //Close the connection with the client
- client.close();
- }
- }
- catch (Exception ioe)
- {
- //In case of exceptions print it to the console.
- System.out.println(ioe);
- }
- }
- }
This will now print whatever your browser is asking from your server to the screen.Once again opening http://localhost/ or http://127.0.0.1/ will give you date on the browser and this output on the console.
Now the browser says GET / HTTP/1.1 (Note: The requests may vary dependent upon the browser you use. Mine is chrome by google). Now this request means GET whatever is there in your / directory, i.e., the root directory your server is broadcasting. And HTTP/1.1 is the version and type it supports. Now though most browsers would just display your html file without any problem if transmitted like this.
- import java.net.*;
- import java.io.*;
- public class Server {
- public static void main(String[] args)
- {
- try
- {
- //Create a socket at port 80. The port over which browser usually connects
- ServerSocket sock = new ServerSocket(80);
- //Go into a loop and wait for connections to occur
- while(true)
- {
- //Accept a connection
- Socket client = sock.accept();
- //Create a buffer to read the client request
- BufferedReader input = new BufferedReader(new InputStreamReader(client.getInputStream()));
- //Print out the requested line
- System.out.println(input.readLine());
- //Create a output stream to send the file
- DataOutputStream output = new DataOutputStream(client.getOutputStream());
- //Open a File to send it over the link
- FileInputStream indexfile = new FileInputStream("C:\\users\\regnarts\\Desktop\\index.html");
- //Buffer for file transfer usage
- byte [] buffer = new byte[1024];
- //loop the transfer mechanism
- while (true)
- {
- //Read and write the file to the buffer
- int b = indexfile.read(buffer, 0,1024);
- if (b == -1) {
- break; //end of file
- }
- output.write(buffer,0,b);
- }
- //Close the file and the output buffer
- output.close();
- indexfile.close();
- //Close the connection with the client
- client.close();
- }
- }
- catch (Exception ioe)
- {
- //In case of exceptions print it to the console.
- System.out.println(ioe);
- }
- }
- }
Edit the file path from my program before you compile it. And create a index.html file (or any other name as long as you are sure that the path points to it). Now if we run the file and open http://localhost/ or http://127.0.0.1/ on browser we get
For the html file, I copied one from the internet that was meant for a html tutorial from http://www.mcli.dist.maricopa.edu/tut/tut1.html. It reads
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
- <html>
- <head>
- <title>Volcano Web</title>
- </head>
- <!-- written for the Writing HTML Tutorial
- by Lorrie Lava, February 31, 1999 -->
- <body>
- In this lesson you will use the Internet to research
- information on volcanoes and then write a report on
- your results.
- </body>
- </html>
Though this must work on most of the browsers it is not the way a server is expected to respond. The server must first output certain bytes that tells the client, status of its request. Perhaps the most famous of these is the "404 File Not Found " error. The correct output to send the index.html file would be
HTTP/1.0 200 OK\r\n Content-Type: text/html\r\n
followed by the index.html file itself. It is not compulsory to transmit index.html itself. But many webservers use it as a default file to be transmitted at the first connection. Try creating a fully working webserver along with security in either android or java. Use concurrency to create different threads to handle every request. Good Luck!!!
HTTP/1.0 200 OK\r\n Content-Type: text/html\r\n
followed by the index.html file itself. It is not compulsory to transmit index.html itself. But many webservers use it as a default file to be transmitted at the first connection. Try creating a fully working webserver along with security in either android or java. Use concurrency to create different threads to handle every request. Good Luck!!!