How to create HTTP Server in Java - ServerSocket Example
Java has a very good networking support, allows you to write
client server application by using TCP Sockets. In this tutorial, we will learn
how to create a simple HTTP Server in Java, which can listen HTTP request on a
port let's say 80 and can send response to client. Being an HTTP Server, you
can connect to it using your browser e.g. Chrome, Firefox or Internet Explorer.
Though HTTP is ubiquitous and present everywhere, Java doesn't have a dedicated
API to create and parse HTTP request, there is no in built HTTP client library
in JDK. Though there is no short of good open source library e.g. you can use
Jsoup to parse HTML and can use Apache HttpClient library for sending GET and
POST request right from your Java program. By the way, for those who wants to
master network programming in Java, I suggest to read Java Network Programming,
4th Addition by Harold, Elliotte Rusty, its very comprehensive and not only
covers both TCP/IP and UDP protocols, which are backbone of internet but also
dive deep into the HTTP protocol, including REST, HTTP headers, and cookies.
Book is very focused on practical and you will find lot of interesting example
related to common networking task e.g. writing multi-threaded servers, using
non blocking IO and using low level socket classes.
How to make HTTP Server in Java
First step to create a web server is to create a network
socket which can accept connection on certain TCP port. HTTP server usually
listen on port 80 but we will use a different port 8080 for testing purpose.
You can use ServerSocket class in Java to create a Server which can accept
requests, as shown below
import java.net.ServerSocket;
public class SimpleHTTPServer {
public static void
main(String[] args) throws Exception {
final ServerSocket
server = new ServerSocket(8080);
System.out.println("Listening for connection on port 8080
....");
while (true){
// spin forever
}
}
}
That's enough to create a web server in Java. Now our server
is ready and listening for incoming connection on port 8080. If you connect to
http://localhost:8080 from your browser, the connection will be established and
browser will wait forever. Don't believe? compile and try it now.
If your browser is smart and giving up after waiting for
sometime then try telnet command. You should be able to connect to server and as
soon as you stop your server telnet will show that "could not open
connection to the host, on port 8080: connect failed" as shown in
following screenshot.
So now we have a server which is listening for connection on
port 8080 but we are not doing anything with incoming connection but we are not
rejecting them either. All of them are waiting to be served and stored inside
server object. Do you see the while(true) loop? Any guess why we have that?
This allows us to keep our program running, without this infinite loop our
program will finish execution and server will be shutdown.
Now let's write code to start accepting connections. In
Java, you can accept incoming connection by blocking call to accept() method,
as shown below :
final Socket client = server.accept();
This is a blocking method and blocks until a client connects
to the server. As soon as a client connect it returns the Socket object which
can be used to read client request and send response to client. Once you are done
with client you should close this socket and get ready to accept new incoming
connection by calling accept() again. So basically, our HTTP server should work
like this:
import java.net.ServerSocket;
import java.net.Socket;
public class SimpleHTTPServer {
public static void
main(String args[] ) throws Exception {
final ServerSocket
server = new ServerSocket(8080);
System.out.println("Listening for connection on port 8080
....");
while (true) {
final Socket
client = server.accept();
// 1. Read HTTP
request from the client socket
// 2. Prepare an
HTTP response
// 3. Send HTTP
response to the client
// 4. Close the
socket
}
}
}
This is the standard HTTP Server, its simple because HTTP is
stateless, which means it doesn't need to remember previous connection, all it
care for new incoming connections. This is endless cycle until server is
stopped. Now let's see what is coming from browser in form of HTTP request.
When you connect to http://localhost:8080,your browser will send a GET HTTP
request to the server. You can read the content of request using InputStream
opened from the client socket. It's better to use BufferedReader because
browser will send multiple line. Here is the code to read request in your HTTP
Server :
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class SimpleHTTPServer {
public static void
main(String args[] ) throws IOException {
ServerSocket
server = new ServerSocket(8080);
System.out.println("Listening for connection on port 8080
....");
while (true) {
Socket
clientSocket = server.accept();
InputStreamReader isr = new
InputStreamReader(clientSocket.getInputStream());
BufferedReader reader = new BufferedReader(isr);
String
line = reader.readLine();
while
(!line.isEmpty()) {
System.out.println(line);
line =
reader.readLine();
}
}
}
}
When you connect to this server using Firefox it will spin
endlessly but on server side you will see following lines on your console :
Listening for connection on port 8080 ....
GET / HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:36.0)
Gecko/20100101 Firefox/36.0
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Our HTTP client (the Firefox browser) passes this text to
our HTTP server written in Java. You can see that request type is GET and
protocol used here is HTTP/1.1.
So now our server is not only listening for connection, but
accepting it and also reading HTTP request. Now only thing remaining is to send
HTTP response back to the client. To keep our server simple, we will just send
today's date to the client. Let's see how we can do that. In order to send
response, we need to get the output stream from socket and then we will write
HTTP response code OK and today's date into stream.
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
/**
* Java program to
create a simple HTTP Server to demonstrate how to use
* ServerSocket and
Socket class.
*
* @author Javin Paul
*/
public class SimpleHTTPServer {
public static void
main(String args[]) throws IOException {
ServerSocket server = new
ServerSocket(8080);
System.out.println("Listening for connection on port 8080
....");
while (true) {
try
(Socket socket = server.accept()) {
Date
today = new Date();
String
httpResponse = "HTTP/1.1 200 OK\r\n\r\n" + today;
socket.getOutputStream().write(httpResponse.getBytes("UTF-8"));
}
}
}
}
When you run the above program in Eclipse or from command
line and connect to the http://localhost:8080 from Firefox,
you will see following response :
you will see following response :
Sun Mar 29 13:32:26 GMT+08:00 2015
Which is today's date. It means our HTTP Server is working
properly, it is listening on port 8080, accepting connection, reading request and
sending response. By using try-with-resource statement of Java 7, we have also
simplified our code, because socket will automatically closed by Java once you
are done with response. Only limitation of this server is that it can serve one
client at a time. If request processing takes longer time, which is not in our
case, the other connection has to wait. This problem can be solved by using
threads or Java NIO non blocking selectors and channels.
That's all about how to create HTTP server in Java. This is
a good example to learn network programming in Java. You have learned how to
use ServerSocket and Socket class from this example. Remember, ServerSocket is
used to receive connections in Server application and Socket is used to send
and receive data from individual client.
No comments:
Post a Comment