Network Socket Programming With Java
All server software is built on the concept of the network socket and internet client applications are also built with the help of sockets. Network sockets are related to the transport layer of the network OSI model. That means it is directly related to TCP and UDP. From the viewpoint of software, sockets live at the lowest level. That means all the internet protocols like HTTP, FTP, etc. depend on the socket. Sockets are used to communicate between two different applications on the network. In other words, sockets are a two way communication link between network applications. With the help of sockets you can create connection oriented TCP links or connection-less UDP links. Sockets have other uses too.
In Java, socket programming is seamless. Unlike C or C++, it is not overly complicated to work with sockets in Java. Again, sockets are not implemented in the same way among all the operating systems. But in Java you do not need to handle all those cross operating system incompatibilities. Java provides abstraction on native socket implementations. So, we can write a socket based application once and run anywhere. All the classes related to socket programming live in the java.net package. We need Socket and ServerSocket from the package java.net to work with TCP sockets. In this article I am not going to discuss UPD sockets, thus covering UDP related classes is irrelevant here.
Socket programming revolves around the concept of a client and a server. The client is a piece of software that requests data from another application on the network. The network can be the internet network, a corporate intranet or the same machine with a loopback address. The other end of it is the server application. A server application continues to run and waits for a client to connect. Once a client is connected, it serves the client or dispatches the request to another process or thread for serving that client. Some well known examples of servers are the Apache web server, Nginx web server, Tomcat web server, MySQL database server, Microsoft SQL server, etc. Clients can be any type of software that sends request to a server to get some data or have some work done. For example the web browser you use everyday is a client, and so is the chat application you use to gossip with your friends.
Getting Started
To get started with socket programming in Java you can use any IDE you like, or you can work without an IDE. Unlike other projects, we’ll need two different projects here: one for the client and the other for the server. After building applications from the project, we will run the server first and then the client. The client will send some data to the server and wait, the server will send some data back and wait for new data.
A real life server should be a multi-threaded server. But to reduce the complication I am not going to make this a multi-threaded server. There may be many people who are reading this article who still do not know about concurrency in Java.
Now, create two projects with a public class in them with a main method. I am going to name the client class as SocketClient and the server class as SocketServer. You are free to choose your name.
Initial SocketClient looks like the following:
import java.net.Socket;
public class SocketClient {
public static void main(String[] args){
}
}
Initial ServerClient looks like the following:
import java.net.ServerSocket;
public class SocketServer {
public static void main(String[] args){
}
}
Socket
The Socket class has several constructors, but we don’t need to learn about them all. The constructor we need accepts two parameters. The first one is the hostname and the second one is the port number. The hostname can be the loopback address or an internet address. It can be a domain/sub-domain name or an IP address. The port number must be an integer. The hostname identifies the machine on which the application we want to connect to runs. The port number is the number on which the server application on that machine is bound to and waiting for a client applications to connect. We want to connect with a server application that is running on local machine on port 2000. So, our hostname is 'localhost' and port number is 2000.
String hostnem = "localhost";
int port = 2000;
Socket soc = new Socket(host, port);
To send data over the wire we need to get the InputStream from the socket object soc and to receive data we need to get InputStream from the socket object.
ServerSocket
ServerSocket class inside java.io package is responsible for handling the functionality related to a socket server. As a constructor it accepts an integer. The integer is a port number. To act as a server, an application must bind to a port number, so that client applications can connect to the application by knowing the hostname of the machine and bound port number of the application. There are three other constructors of ServerSocket, but here we do not need to learn them all.
int portNo = 2000;
ServerSocket ssoc = new ServerSocket(portNo);
Remember that without being a root user or administrator user you cannot bind to a port number from 0 to 1023. That range of port numbers is used for commonly used protocols and servers. For example, 80 is used for HTTP servers. Also, remember that only one application at a time can bind to a specific port number.
To accept a request from a client application we need to invoke the accept() method on the ServerSocket object. accept() returns a Socket object. We can read and write on the socket object to receive and send data to the connected client.
int portNo = 2000;
ServerSocket ssoc = new ServerSocket(portNo);
Socket csoc = ssoc.accept();
Our Applications
We want to develop a client that will send 'Hi' to the server application and the server application will send 'Bye' in return. Again, the client will send 'Bye Bye!' and the server will send 'Ta Ta!' in return. After that we will close our connection.
The client code should look like the following:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class SocketClient {
public static void main(String[] args) throws Exception{
int portNo = 2000;
String host = "localhost";
Socket csoc = new Socket(host, portNo);
BufferedReader br = new BufferedReader( new InputStreamReader(csoc.getInputStream()) );
BufferedWriter bw = new BufferedWriter( new OutputStreamWriter(csoc.getOutputStream()) );
bw.write("Hi\n");
bw.flush();
System.out.println("Server: " + br.readLine());
bw.write("Bye Bye\n");
bw.flush();
System.out.println("Server: " + br.readLine());
br.close();
bw.close();
csoc.close();
System.out.println("The message exchange ended!");
}
}
And the server code should look like the following:
import java.net.ServerSocket;
import java.net.Socket;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.BufferedReader;
import java.io.BufferedWriter;
public class SocketServer {
public static void main(String[] args) throws Exception{
int portNo = 2000;
ServerSocket ssoc = new ServerSocket(portNo);
Socket csoc = ssoc.accept();
BufferedReader br = new BufferedReader( new InputStreamReader(csoc.getInputStream()) );
BufferedWriter bw = new BufferedWriter( new OutputStreamWriter(csoc.getOutputStream()) );
String line = "";
while ( (line = br.readLine()) != null ){
line = line.trim();
if (line.equals("Hi")){
bw.write("Bye\n");
}else if( line.equals("Bye Bye") ){
bw.write("Ta Ta!\n");
}
System.out.println("Client: " + line);
bw.flush();
}
br.close();
bw.close();
csoc.close();
System.out.println("The client has closed the connection!");
}
}
Output from the server is:
Client: Hi
Client: Bye Bye
The client has closed the connection!
Output from the client is:
Server: Bye
Server: Ta Ta!
The message exchange ended!
I did not explicitly handled the exceptions. I avoided all the exception by using the root exception Exception. You are advised to handle exceptions properly for particular use cases. Also, I flushed often on the stream, so that no read/write is kept hanging for more data to be buffered. Also, note that I have closed all the resources. You must follow the steps properly to develop a better server and client.
Compared to other programming languages, socket programming in Java is breeze. You can develop any type of custom service and expose that to the world with the help of socket programming. You can create the next Apache, Nginx, Tomcat, another custom server, etc. by gaining enough knowledge of socket programming and a few other things. And all those come with the sweetness of cross platform compatibility. Read more about the Socket and ServerSocket class in the official documentation from Oracle.
Recent Stories
Top DiscoverSDK Experts
Compare Products
Select up to three two products to compare by clicking on the compare icon () of each product.
{{compareToolModel.Error}}
{{CommentsModel.TotalCount}} Comments
Your Comment