Java socket programming tutorial

36 Flares Filament.io 36 Flares ×

Socket programming in Java

This is a quick guide/tutorial to learning socket programming in Java.

The Socket class is documented at http://docs.oracle.com/javase/1.4.2/docs/api/java/net/Socket.html

To summarise the basics, sockets are the fundamental "things" behind any kind of network communications done by your computer. For example when you type www.google.com in your web browser, it opens a socket and connects to google.com to fetch the page and show it to you. Same with any chat client like gtalk or skype. Any network communication goes through a socket.

Before you begin

This tutorial assumes that you already have a basic knowledge of java and can compile and run java programs.

So lets begin with sockets.

Creating a socket

This first thing to do is create a socket.

Quick Example :

Socket s = new Socket();

The above creates a socket object that can be used for other operations like connecting and sending data.
The socket class is actually a TCP socket, although its not specified (like its done in C or python for example).
Also, it is a "client socket" since it can be used only to make socket clients and not servers. More on this later in this article.

UDP sockets in java are created using the class DatagramSocket, and we shall look into this in another article.

Ok , so you have created a socket successfully. But what next ? Next we shall try to connect to some server using this socket. We can connect to www.google.com

Connect to a Server

We connect to a remote server on a certain port number. So we need 2 things , IP address and port number to connect to. So you need to know the IP address of the remote server you are connecting to. Here we used the ip address of google.com as a sample.

Now that we have the ip address of the remote host/system, we can connect to ip on a certain 'port' using the connect function.

Quick example

//java socket client example
import java.io.*;
import java.net.*;

public class socket_client
{
    public static void main(String[] args) throws IOException 
    {
        Socket s = new Socket();
	String host = "www.google.com";
		
        try 
        {
		s.connect(new InetSocketAddress(host , 80));
        }
        
        //Host not found
        catch (UnknownHostException e) 
        {
            System.err.println("Don't know about host : " + host);
            System.exit(1);
        }
        
        System.out.println("Connected");
    }
}






Run the program

$ javac socket_client.java && java socket_client
Connected

It creates a socket and then connects. Try connecting to a port different from port 80 and you should not be able to connect which indicates that the port is not open for connection. This logic can be used to build a port scanner.

Tip

The Socket object can be connected at the time of creation.

Socket s = new Socket(host , port);

OK, so we are now connected. Lets do the next thing , sending some data to the remote server.

Sending Data


//java socket client example
import java.io.*;
import java.net.*;

public class socket_client
{
    public static void main(String[] args) throws IOException 
    {
        Socket s = new Socket();
	String host = "www.google.com";
	PrintWriter s_out = null;
		
        try 
        {
		s.connect(new InetSocketAddress(host , 80));
		System.out.println("Connected");
			
		//writer for socket
            s_out = new PrintWriter( s.getOutputStream(), true);
        }
        
        //Host not found
        catch (UnknownHostException e) 
        {
            System.err.println("Don't know about host : " + host);
            System.exit(1);
        }
        
        //Send message to server
	String message = "GET / HTTP/1.1\r\n\r\n";
	s_out.println( message );
			
	System.out.println("Message send");
    }
}

In the above example , we first connect to www.google.com and then send the string message "GET / HTTP/1.1\r\n\r\n" to it. The message is actually an "http command" to fetch the mainpage of a website.

Now that we have send some data , its time to receive a reply from the server. So lets do it.

Receiving Data


//java socket client example
import java.io.*;
import java.net.*;

public class socket_client
{
    public static void main(String[] args) throws IOException 
    {
        Socket s = new Socket();
	String host = "www.google.com";
	PrintWriter s_out = null;
	BufferedReader s_in = null;
		
        try 
        {
		s.connect(new InetSocketAddress(host , 80));
		System.out.println("Connected");
			
		//writer for socket
            s_out = new PrintWriter( s.getOutputStream(), true);
            //reader for socket
            s_in = new BufferedReader(new InputStreamReader(s.getInputStream()));
        }
        
        //Host not found
        catch (UnknownHostException e) 
        {
            System.err.println("Don't know about host : " + host);
            System.exit(1);
        }
        
        //Send message to server
	String message = "GET / HTTP/1.1\r\n\r\n";
	s_out.println( message );
			
	System.out.println("Message send");
		
	//Get response from server
	String response;
	while ((response = s_in.readLine()) != null) 
	{
		System.out.println( response );
	}
    }
}

Here is the output of the above code :

$ javac socket_client.java && java socket_client
Connected
Message send
HTTP/1.1 302 Found
Location: http://www.google.co.in/
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Set-Cookie: domain=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=.google.com
Set-Cookie: PREF=ID=8cab6cb84196272d:FF=0:TM=1343284818:LM=1343284818:S=v6CKP6OQ7-MwR9Ho; expires=Sat, 26-Jul-2014 06:40:18 GMT; path=/; domain=.google.com
Set-Cookie: NID=62=g7qvBSlfd6RLHqowhnvlKcu1hr3EtfMzv39ggUYhjtC0ow7-2gTW5mVnePH5HyRS5D2oB4UAmbGCZTVs0MF6EQojZRTuhSd-6-9qaJeyfegjHvNwarfE8yB5Kz_I8GS0; expires=Fri, 25-Jan-2013 06:40:18 GMT; path=/; domain=.google.com; HttpOnly
P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info."
Date: Thu, 26 Jul 2012 06:40:18 GMT
Server: gws
Content-Length: 221
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.co.in/">here</A>.
</BODY></HTML>

google.com replied with the content of the page we requested. Quite simple!
Now that we have received our reply, its time to close the socket.

Close socket

Function close is used to close the socket.

//close the i/o streams
s_out.close();
in.close();
		
//close the socket
s.close();

Thats it.

Lets Revise

So in the above example we learned how to :
1. Create a socket
2. Connect to remote server
3. Send some data
4. Receive a reply

Its useful to know that your web browser also does the same thing when you open www.google.com
This kind of socket activity represents a CLIENT. A client is a system that connects to a remote system to fetch data.

The other kind of socket activity is called a SERVER. A server is a system that uses sockets to receive incoming connections and provide them with data. It is just the opposite of Client. So www.google.com is a server and your web browser is a client. Or more technically www.google.com is a HTTP Server and your web browser is an HTTP client.

Now its time to do some server tasks using sockets.

Server Programming

OK now onto server things. Servers basically do the following :

1. Open a socket
2. Bind to a address(and port).
3. Listen for incoming connections.
4. Accept connections
5. Read/Send

We have already learnt how to open a socket. So the next thing would be to bind it.

Bind socket to a port

To create a socket and bind it to a particular port number, all that needs to be done is to create an object of class ServerSocket. The constructor takes 2 parameters, first is the local port number and the 2nd is the backlog number.

Quick example

ServerSocket s = new ServerSocket(5000 , 10);

The above piece of code will create a socket and bind it to local machine port number 5000. Its important to note that the socket is already listening for connections. So the next thing is to accept connections by calling the accept method on the socket.

Accept connection

Function accept is used for this.

//java server example
import java.io.*;
import java.net.*;

public class socket_server
{
	public static void main(String args[])
	{
		ServerSocket s = null;
		Socket conn = null;
		PrintStream out = null;
		BufferedReader in = null;
		String message = null;
		
		try
		{
			//1. creating a server socket - 1st parameter is port number and 2nd is the backlog
			s = new ServerSocket(5000 , 10);
			
			//2. Wait for an incoming connection
			echo("Server socket created.Waiting for connection...");
			//get the connection socket
			conn = s.accept();
			//print the hostname and port number of the connection
			echo("Connection received from " + conn.getInetAddress().getHostName() + " : " + conn.getPort());
			
			//3. get Input and Output streams
			out = new PrintStream(conn.getOutputStream());
			out.flush();
			in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
			
			out.println("Welcome. Server version 1.0");
			out.flush();
		}
		
		catch(IOException e)
		{
			System.err.println("IOException");
		}
		
		//5. close the connections and stream
		try
		{
			in.close();
			out.close();
			s.close();
		}
		
		catch(IOException ioException)
		{
			System.err.println("Unable to close. IOexception");
		}
	}
	
	public static void echo(String msg)
	{
		System.out.println(msg);
	}
}

Output

Run the program. It should show

$ javac socket_server.java && java socket_server
Server socket created.Waiting for connection...

So now this program is waiting for incoming connections on port 5000. Dont close this program , keep it running.
Now a client can connect to it on this port. We shall use the telnet client for testing this. Open a terminal and type

$ telnet localhost 5000

It will immediately show

$ telnet localhost 5000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Welcome. Server version 1.0
Connection closed by foreign host.

And the server output will show

$ javac socket_server.java && java socket_server
Server socket created.Waiting for connection...
Connection received from localhost : 34513

So we can see that the client connected to the server. Try the above steps till you get it working perfect.

We accepted an incoming connection but closed it immediately. This was not very productive. There are lots of things that can be done after an incoming connection is established. Afterall the connection was established for the purpose of communication.

Simple ECHO server

Now lets modify the above program such that it takes some input from client and replies back with the same message.

//java server example
import java.io.*;
import java.net.*;

public class socket_server
{
	public static void main(String args[])
	{
		ServerSocket s = null;
		Socket conn = null;
		PrintStream out = null;
		BufferedReader in = null;
		String message = null;
		
		try
		{
			//1. creating a server socket - 1st parameter is port number and 2nd is the backlog
			s = new ServerSocket(5000 , 10);
			
			//2. Wait for an incoming connection
			echo("Server socket created.Waiting for connection...");
			//get the connection socket
			conn = s.accept();
			//print the hostname and port number of the connection
			echo("Connection received from " + conn.getInetAddress().getHostName() + " : " + conn.getPort());
			
			//3. get Input and Output streams
			out = new PrintStream(conn.getOutputStream());
			out.flush();
			in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
			
			out.println("Welcome. Server version 1.0");
			out.flush();




			//4. The two parts communicate via the input and output streams
			do
			{
				//read input from client
				message = (String)in.readLine();
				echo("client>" + message);
				
				if(message != null)
				{
					out.println(message);
				}
				else
				{
					echo("Client has disconnected");
					break;
				}
			}
			while(!message.equals("bye"));
		}
		
		catch(IOException e)
		{
			System.err.println("IOException");
		}
		
		//5. close the connections and stream
		try
		{
			in.close();
			out.close();
			s.close();
		}
		
		catch(IOException ioException)
		{
			System.err.println("Unable to close. IOexception");
		}
	}
	
	public static void echo(String msg)
	{
		System.out.println(msg);
	}
}

Run the above code in 1 terminal. And connect to this server using telnet from another terminal and you should see this :

$ telnet localhost 5000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Welcome. Server version 1.0
hi
hi
how are you
how are you

So the client(telnet) received a reply from server.

In the above example we can see that the server is handling the client very well. But there is a problem. It can only handle one client at a time. If other clients connect to it, they would get connected but nothing more would happen.

Handling Multiple Connections

To handle every connection we need a separate handling code to run alongside the main server that is accepting new connections. One way to achieve this is using threads. The main server program accepts a connection and creates a new thread to handle communication for the connection, and then the server goes back to accept more connections.

We shall now use threads to create handlers for each connection the server accepts.

//java server example
import java.io.*;
import java.net.*;

public class socket_server
{
	public static void main(String args[])
	{
		ServerSocket s = null;
		Socket conn = null;
		
		try
		{
			//1. creating a server socket - 1st parameter is port number and 2nd is the backlog
			s = new ServerSocket(5000 , 10);
			
			//2. Wait for an incoming connection
			echo("Server socket created.Waiting for connection...");
			
			while(true)
			{
				//get the connection socket
				conn = s.accept();
				
				//print the hostname and port number of the connection
				echo("Connection received from " + conn.getInetAddress().getHostName() + " : " + conn.getPort());
				
				//create new thread to handle client
				new client_handler(conn).start();
			}
		}
		
		catch(IOException e)
		{
			System.err.println("IOException");
		}
		
		//5. close the connections and stream
		try
		{
			s.close();
		}
		
		catch(IOException ioException)
		{
			System.err.println("Unable to close. IOexception");
		}
	}
	
	public static void echo(String msg)
	{
		System.out.println(msg);
	}
}

class client_handler extends Thread 
{
    private Socket conn;
    
    client_handler(Socket conn) 
    {
		this.conn = conn;
    }

	public void run() 
    {
		String line , input = "";
		
		try
		{
			//get socket writing and reading streams
			DataInputStream in = new DataInputStream(conn.getInputStream());
			PrintStream out = new PrintStream(conn.getOutputStream());

			//Send welcome message to client
			out.println("Welcome to the Server");

			//Now start reading input from client
			while((line = in.readLine()) != null && !line.equals(".")) 
			{
				//reply with the same message, adding some text
				out.println("I got : " + line);
			}
			
			//client disconnected, so close socket
			conn.close();
		} 
      
		catch (IOException e) 
		{
			System.out.println("IOException on socket : " + e);
			e.printStackTrace();
		}
    }
}

Run the above server and open 3 terminals like before. Now the server will create a thread for each client connecting to it.

The telnet terminals would show :

$ telnet localhost 5000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Welcome to the Server
hi
I got : hi
how are you
I got : how are you
i am fine
I got : i am fine

The server terminal might look like this

$ javac socket_server.java && java socket_server 
Server socket created.Waiting for connection...
Connection received from localhost : 34907
Connection received from localhost : 35097

The above connection handler takes some input from the client and replies back with the same.

So now we have a server thats communicative. Thats useful now.

Conclusion

By now you must have learned the basics of socket programming in Java. You can try out some experiments like writing a chat client or something similar.

If you think that the tutorial needs some addons or improvements or any of the code snippets above dont work then feel free to make a comment below so that it gets fixed.

Last Updated On : 13th November 2012

Subscribe to get updates delivered to your inbox

About Silver Moon

Php developer, blogger and Linux enthusiast. He can be reached at m00n.silv3r@gmail.com. Or find him on

  • Ernesto Ibáñez

    Wow!!!! so excellent Web site. I need this for my new Java project.
    Thanks a lot for this gold code. Very Cool.

    see my blog also

  • Swarne

    Can u please explain how to check whether the sent message from TCP is received or not?

  • Ahmet Kamiş

    Hi, I tried connect a socket with multiple threads and using bruteforce.After 5-6 minute I got an exception “java.lang….to many open socket” ….can anyone help me.

  • fanlee

    thank you very much, i got a lot of knowledge from your website.

  • http://www.facebook.com/profile.php?id=1365145650 Kevin John

    Thank you for a great tutorial on Java Sockets, so many of the tutorials that I found previously used lots of deprecated functions and classes. Also, I like that you built up the client file talking to an existing server (google) instead of relying on the user to create a working server and client simultaneously. Excellent pedagogy.

  • pulkit

    Helped a great deal!!
    Many Thanks :)

  • Deepankar

    Hi,

    It is very useful.

    I am making a proxy server using socket connection.

    I want to add features in the proxy server like redirecting the browser to a login page if the user has not login. When user has login, it will be able to do browsing but when a certain time is exhausted, it is again redirected to a login page. When the user login again, the user will be able to continue from the page its was redirected.

    I am stuck in the initial phase where I want to redirect user to lets say google.com.

    I have typed http://www.yahoo.com and trying to redirect to http://www.google.com

    I am getting following error

    “Connected
    HTTP/1.1 302 Found
    Location: http://www.google.co.in/
    Cache-Control: private
    Content-Type: text/html; charset=UTF-8
    Set-Cookie: PREF=ID=17a9d84072c36e0d:FF=0:TM=1351049168:LM=1351049168:S=fNiwPQZ0kpEqwhYX; expires=Fri, 24-Oct-2014 03:26:08 GMT; path=/; domain=.google.com
    Set-Cookie: NID=65=JmrJPskllovAw2EMLuiQWUDmfV3WxU_PaU_lXDiVtfN5ag8BFALND6XkhpZ8Y5mx4qtt-86Bo1AAvohsSkZ5H7fZ4Iaerbc8TaTsagrirb-nBmKi3M97qiPhnIZzkBcb; expires=Thu, 25-Apr-2013 03:26:08 GMT; path=/; domain=.google.com; HttpOnly
    P3P: CP=”This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info.”
    Date: Wed, 24 Oct 2012 03:26:08 GMT
    Server: gws
    Content-Length: 221
    X-XSS-Protection: 1; mode=block
    X-Frame-Options: SAMEORIGIN

    302 Moved
    302 Moved
    The document has moved
    here.

    p://www.googHTTP/1.0 400 Bad requestCache-Control: no-cacheConnection: closeContent-Type: text/html400 Bad requestYour browser sent an invalid request.IO Exception Software caused connection abort: recv failed
    java.net.SocketException: Software caused connection abort: recv failed
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.read(SocketInputStream.java:129)
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
    at java.io.InputStreamReader.read(InputStreamReader.java:167)
    at java.io.BufferedReader.fill(BufferedReader.java:136)
    at java.io.BufferedReader.readLine(BufferedReader.java:299)
    at java.io.BufferedReader.readLine(BufferedReader.java:362)
    at proxyservers.dwgold.ProxyThread.run(ProxyThread.java:50)
    Java Result: 1″

    This is the code base

    import java.net.*;
    import java.io.*;
    import java.lang.*;
    import java.util.*;
    import java.util.logging.Level;
    import java.util.logging.Logger;

    class ProxyThread extends Thread {

    Socket incoming, outgoing;
    boolean toServer;

    ProxyThread(Socket in, Socket out, boolean toserver) {
    incoming = in;
    outgoing = out;
    toServer = toserver;
    }

    // Overwritten run() method of thread,
    // does the data transfers
    @Override
    public void run() {
    byte[] buffer = new byte[60];
    int numberRead = 0;

    String meta = “”;
    try {

    if (toServer) {
    OutputStream toClient;
    InputStream fromClient;

    toClient = outgoing.getOutputStream();
    fromClient = incoming.getInputStream();

    while (true) {
    String response;
    BufferedReader inReader = null;
    inReader = new BufferedReader(new InputStreamReader(fromClient));
    while ((response = inReader.readLine()) != null) {
    System.out.print(“” + response);
    buffer = response.getBytes();
    toClient.write(buffer, 0, response.getBytes().length);
    }

    // numberRead = fromClient.read(buffer, 0, 50);
    //String browserRequest = new String(buffer, 0, 50);
    //meta = browserRequest;
    // if (toServer) {
    // System.out.print(“” + meta);
    // } else {
    // System.out.print(“” + meta);
    // }

    // forward the response from the proxy to the server
    if (numberRead == -1) {
    incoming.close();
    outgoing.close();
    }

    //System.out.println(“Forwarding request to server”);
    //toClient.write(buffer, 0, numberRead);
    }
    } else {
    String url = “www.google.com”;
    //URL server = new URL(url);
    //HttpURLConnection connection = (HttpURLConnection) server.openConnection();
    //connection.connect();
    Socket redirect = new Socket();
    PrintWriter outWriter = null;
    redirect.connect(new InetSocketAddress(url, 80));
    System.out.println(“Connected “);
    //writer for socket
    outWriter = new PrintWriter(redirect.getOutputStream(), true);
    //Send message to server
    String message = “GET / HTTP/1.1\r\n\r\n”;
    outWriter.println(message);

    //writer for socket
    outWriter = new PrintWriter(redirect.getOutputStream(), true);

    InputStream fromClient = redirect.getInputStream();

    OutputStream toClient = outgoing.getOutputStream();

    while (true) {
    numberRead = fromClient.read(buffer, 0, 50);
    String browserRequest = new String(buffer, 0, 50);
    meta = browserRequest;
    if (toServer) {
    System.out.print(“” + meta);
    } else {
    System.out.print(“” + meta);
    }
    // forward the response from the proxy to the server
    if (numberRead == -1) {
    redirect.close();
    outgoing.close();
    }
    //System.out.println(“Forwarding request to server”);
    toClient.write(buffer, 0, numberRead);
    }
    // readResponse(fromClient, toClient);
    }

    } catch (UnknownHostException e) {
    System.err.println(“Don’t know about host : “);
    System.exit(1);
    } catch (IOException e) {
    System.out.println(“IO Exception ” + e.getMessage());
    e.printStackTrace();
    System.exit(1);
    } catch (ArrayIndexOutOfBoundsException e) {
    System.out.println(“Array Exception ” + e.getMessage());
    e.printStackTrace();
    System.exit(1);
    }

    }
    }

    The else case is where the socket listen to the request going from local system to the remote system and the if case is where the socket listen to the incoming response.

    Please guide

  • tyfn

    Very useful, thanks ! Loved your website :)

36 Flares Twitter 9 Facebook 19 Google+ 5 LinkedIn 0 StumbleUpon 3 Filament.io 36 Flares ×