Socket Programming in Java | Sending Text Files Between Server and Client

In order to understand socket programming in java and how to send text files between server and client, you need to first comprehend the basics of networking.

You see networking is nothing but a connection. When you connect two things together in such a way you can pass around data to and fro, they are said to have established a network. A very good example of networking could be something as basic as a messenger, where you spend all day sending data from one device to the other.

funny chat dad

There are thousands of times when you are required to send something over a network. Could be a minor interaction with a client system, or simply something you wish to send across to receive that “hello from the other side”. That’s where socket programming in Java jumps in.

Networking Terms

I will throw in a couple of terms just to break the ice, so you know what you are dealing with here. I wouldn’t go really deep into computer networking because it’s a really vast topic and we don’t need much to understand socket programming in Java. So we are just going to skim it.

IP Address

It is like a phone number but for computers. You can’t dial it for pizza though. Each computer is allotted an IP Address which goes something like this:

192.168.0.1

Each number before the ‘.’ and after is an octet. So we have four octets that range between 0 to 255. IP address is also known as logical address and can be changed.

Well, what if I tell you your system’s got an IP Address too. Here’s how to check that out:

Just go to your command prompt (cmd) and type

 ipconfig

Then press Enter:

typing ipconfig on cmd to identify IP Address

You see that reddened bit against IPv4 Address, that’s your IP address right there.

Protocol

Protocol is exactly what it means what you think it means. A set of rules that is followed by your system for network communication. Each set of rules has been defined based upon the kind of message it sends across a network.

For e.g.

  • TCP – Transmission Control Protocol (Acknowledgement sent by the receiver/ connection oriented protocol)
  • UDP – User Datagram Protocol (No acknowledgement sent by receiver/ connection less protocol)

Other examples would be:

  • HTTP – Hyper Text Transfer Protocol
  • FTP – File Transfer Protocol
  • SMTP – Simple Mail Transfer Protocol
  • Telnet

Port Number

If we are still talking about telephones here, port number is nothing but an extension. It is needed to make your system understand where the connection needs to be established.

Each port number identifies an application. So what application do we need to establish connection with, has to be predefined.

It is a 16-bit unsigned integer with a value that ranges from 0 to 65535.

So how does the second computer or device know where to reroute that incoming package? You see every data packet that is sent retains a port number in its header file that tells the system where the packet should really go.

Socket

A cardinal point to learn socket programming in Java. A socket is nothing but an end point on either side of the two computers or devices that are either responsible for sending or receiving the data over a network. The data is sent to a single node. There’s a port number allotted to each socket so that the computer understands where the data needs to be sent.

So the socket address would be a collection of both IP address and Port No. conjoined together.

An e.g.

192.168.0.1: 8080

When you provide a socket with a socket address it is called binding.

MAC Address

Just like there is a logical address, every system has got a physical address too. Unlike logical address or IP address, it is unchangeable. It identifies with your NIC (Network Interface Controller) and is hardcoded on it.

MAC is an acronym for Media Access Control. It is a collection of 6 octets here. You can check out the MAC Address by simply typing the following in your command prompt:

ipconfig -all

As you can see different adapters have their own Physical Addresses however each physical address identifying that adapter or NIC will always be unique:

MAC Address identification

So it is clear that they are two systems involved when you are trying to send something and the other system is trying to receive it. For our example, we wouldn’t need two systems, although you can try it on two and it will work there still. There is this localhost with IP address:

127.0.0.1

which basically refers to your very own system. We can use it to send our data and receive it simultaneously on our system. The behaviour would be as if we are sending it to a different system.

Socket Programming in Java

When you are trying to make a connection between applications that are on different JREs, that’s where socket programming in Java comes into the picture.

Here the connection established could be either connection-oriented or connection-less.

If you wish to opt for connection-oriented programming, the following Classes come in handy: (TCP)

  • Socket
  • ServerSocket

If you want to go for connection-less programming, the following Classes come to the rescue: (UDP)

  • DatagramSocket
  • DatagramPacket

We will see connection-oriented programming first to understand socket programming in Java.

Socket Class

Socket Class is one of the crucial classes that you must know about as part of socket programming in Java. We use it at the client side.

The Socket Class is the one that directly extends Object. It serves as an endpoint between two machines.

Here are the constructors of Socket class that you could use:

  1. Socket()
  2. Socket(InetAddress address, int port)
  3. Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
  4. Socket(Proxy proxy)
  5. Socket(SocketImpl impl)
  6. Socket(String host, int port)
  7. Socket(String host, int port, InetAdress localAddr, int localPort)

There are so many methods here that you could use in order to get things done. However, the most important methods that you need to remember are:

  • getInputStream()
  • getOutputStream()
  • close()

The first two methods return InputStream and OutputStream against the socket respectively. close() returns void and is used to close the socket. It is synchronized by default.

So while writing a program for socket programming in Java we need to specify it in the following format:

Socket s = new Socket("localhost", 6666);

where the first argument is the localhost address which you can replace with any other computer’s IP Address while the second argument is that of port no.

ServerSocket Class

Another important Class that tells you more about socket programming in Java. You use it at the Server’s end.

When you have a connection to establish with a computer, we make use of the ServerSocket class. You create a server socket with it.

A server socket basically waits for a request to show up in the network. Once the request is received it performs the necessary action at the same time sends an acknowledgement back to the sender.

Here are the constructors you could use in order to create a ServerSocket class:

  1. ServerSocket()
  2. ServerSocket(int port)
  3. ServerSocket(int port, int backlog)
  4. ServerSocket(int port, int backlog, InetAddress bindAddr)

Important methods to remember here are:

  • accept()
  • close()

The accept() method returns socket by listening to the connection and establishing one.

So while writing a program for socket programming in Java you need to write it in the following format:

ServerSocket ss  = new ServerSocket(6666);

where 6666 is nothing but the port no. where the connection is established.

Then we need wait for the client socket using the accept() method that returns Socket. Hence the next code should be

Socket s = ss.accept();

Program to Transfer Data from Client to Server

Now we will see a program to comprehend socket programming in Java. It will help in clearing the whole picture. We will do this the old-fashioned way. Without resorting to using Eclipse. Let’s just create two separate notepad files one depicting client and the other server.

Here’s our two notepad files, looking all nice and happy.

two blank notepad files named client and server

Steps to Send Data Across

While socket programming in Java you need to first have the correct packages at your disposal.

Step 1: Import the relevant packages first. You don’t want the compiler to fling an Error across saying it doesn’t recognize the stuff you have been typing.

Write the following at the top:

import java.net.*;
import java.io.*;

The first one is for all the networking classes including Socket and ServerSocket. The second is for input and output classes.

So what are the things that we need to do?

Client Code for Sending Data Across

It is the Client that will send the data. We will make use of DataOutputStream Class to send out some data.

Step 2: Write the following code in the client notepad file. Here’s the code to be typed:

import java.net.*;
import java.io.*;
public class Client {
public static void main (String []args) {
   try {
        Socket s = new Socket("localhost", 1999);
        DataOutputStream dos = new DataOutputStream(s.getOutputStream());
        dos.writeUTF("If procrastination was a sport, I would compete in it later.");
       } catch (IOException ie) {
         ie.printStackTrace();
       }
    }
}

Notice how we have made use of writeUTF() method. It will help in passing along a String in Unicode format. We have a contrasting readUTF method in DataInputStream class that can read it easily.

We have made use of Socket’s (String host, int port) constructor here. Port no. you can use any.

Step 3: Save the file as “Client.java”.

NOTE: We haven’t closed the socket and DataOutputStream, it is always a good idea to close them.

Server Code for Listening for Connections

It is a Server’s job to listen for connections and establish if there is one. The code here is going to be fairly simple to fathom.

Step 4: Write the following code in the Server notepad file that you have created:

import java.net.*;
import java.io.*;

public class Server {
public static void main (String []args) {
       try {
                ServerSocket ss = new ServerSocket(1999);
                Socket s = ss.accept();
                DataInputStream dis=new DataInputStream(s.getInputStream());
                System.out.println(dis.readUTF());
                } catch (IOException ie) {
                  ie.printStackTrace();
                }
       }
}

Here all we need to do is listen. Accept() method helps us to do us exactly that. Also, we need to provide the port no. Make sure it’s the same meaning in perfect sync with the node.

Step 5: Save the file as “Server.java”.

NOTE: We haven’t closed the ServerSocket reference and DataInputStream, it is always a good idea to close them.

Compilation and Execution

Now it’s time to compile the program and then execute it.  If you have forgotten how to do that on cmd you can always flip back to check out that first Java Demo program we did in the very beginning.

Step 6: Open two command prompt windows like this:

two command prompt windows

Make sure you have navigated to the location where you have saved your files “Client.java” and “Server.java”.

Step 7: Compile both the files in each window by entering the following commands one by one:

javac Client.java

javac Server.java

You can do it in the same window. The compilation doesn’t care about the windows really.

After compilation, you will find Client.class and Server.class created in your folder which are nothing but the bytecodes.

Step 8: Now in one of the cmd windows run the following command first:

java Server

Type the aforementioned and press Enter.

running server program in cmd prompt

Server’s job is to listen for connections and so you will see nothing has really happened. Your cursor would be blinking for attention is all.

Step 9: In the second cmd window run the other program by typing:

java Client

and then press enter.

client command prompt

You will notice that as soon as you press enter the message that you were intending to transfer to the Server patches through.

Here’s the result that you should get:

message delivered via cmd prompts socket programming in java

This means our connection has successfully been established and the message has successfully been displayed across the network.

Now let’s make this a two-way conversation. Just like a chat window where you are chatting with a friend and the message patches through every time you press enter.

Chatting Window

We don’t need to make many changes in our code above. In fact, just prepare it for a two-way conversation. So, where we were just using a DataOutputStream we need to include a DataInputStream as well and vice versa.

Client Side Code

Let’s quickly see what our client side java file should have:

Step 1: Create a new notepad file or you could use the existing Client.java file to update the following code in it:

import java.net.*;
import java.io.*;
public class Client {
public static void main (String []args) {
   try {
        Socket s = new Socket("localhost", 1999);
        DataOutputStream dos = new DataOutputStream(s.getOutputStream());
        DataInputStream dis = new DataInputStream(s.getInputStream());
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        while(!br.readLine().equals("quit")) { 
        dos.writeUTF(br.readLine());
        System.out.println("He says: " + dis.readUTF());   
        dos.flush();          
        }
        s.close();
        } catch (IOException ie) {
         ie.printStackTrace();
       }
    }
}

As you can see we are going to need a BufferedReader and InputStreamReader to identify keyboard inputs and send them across. That’s where System.in comes into picture. We used a while loop to identify a “quit” word when used shall close all connections.

Step 2: Save the file as Client.java if you haven’t already.

Server Side Code

Let’s see what the Server-side code should entail:

Step 3: Create a new Server.java or you can use the existing Server file to update the code with the following code:

import java.net.*;
import java.io.*;

public class Server {
public static void main (String []args) {
try { 
             ServerSocket ss = new ServerSocket(1999);
             Socket s = ss.accept();    
             DataOutputStream dos = new DataOutputStream(s.getOutputStream());       
             DataInputStream dis = new DataInputStream(s.getInputStream());        
             BufferedReader br = new BufferedReader(new InputStreamReader(System.in));       
             while(!br.readLine().equals("quit")) {        
                      System.out.println("She says: " + dis.readUTF());         
                      dos.writeUTF(br.readLine());             
                      }        
                      ss.close();         
               } catch (Exception ie) { 
                 ie.printStackTrace(); 
        }    
    }
}

As we can see here the code is going to be fairly similar. Only thing is here we would be using ServerSocket’s accept method to listen to the exact port.

Step 4: Save the file as Server.java if you haven’t saved it already.

Compiling and Executing the Chat Program

Step 5: Open two separate command Prompt windows and compile both the programs using:

javac Client.java

javac Server.java

Again you can do so in the same window.

Step 6: After compilation, in one of the windows type:

java Server

and press Enter.

This would prepare the Server for listening to the port.

Step 7: In the other cmd window type:

java Client

and press Enter.

Start the conversation.

conversation chat window

Step 8: If you wish to quit you can type quit anytime and get out of it.

Go ahead and try this on different systems over a network.

NOTE: You can also use Ctrl + C to get out of it.

Now since we can do this, can’t we send files across the network too? In words of The Great Gatsby:

“Why of course you can.”

Sending Text Files Between Server and Client

Bringing our previous lessons of how to read from a file and how to write to a file to a good use, we will see how to send a text file between server and client.

Since we can send data from one computer to another, doing so with a file wouldn’t be any hard work.

Here we would need an existing file. I have created a txt file named nadal. The following information has been put in it.

nadal notepad info

Now let’s try to create the client side of it that would be reading the above file and then sending its data across:

Creating Client.java

Step 1: Create a new notepad file or you could use the earlier created Client.java file to update its content. Enter the following code:

import java.net.*;
import java.io.*;

public class Client {
public static void main(String[] args) { 

         try {
                 Socket s = new Socket("localhost", 1999); 
                 BufferedReader br = new BufferedReader(new FileReader("E:\\nadal.txt")); 
                 byte []b = new byte[30]; 
                 String k = br.readLine(); 
                 DataOutputStream dos = new DataOutputStream(s.getOutputStream()); 
                 dos.writeUTF(k); 
                 System.out.println("Transfer Complete"); 
                } catch (IOException ie) {
                   ie.printStackTrace(); 
               }
      }
}

Here the first and the foremost thing to announce is the Socket info where you wish to make the connection. Since we are dealing with our very own system, we have used “localhost”, you could use the IP of another system if you have one. The port no. has been provided as well.

Then it was time to read the stuff in the text file nadal. We can do so using BufferedReader and FileReader. Then we need to send the data on the Output stream. writeUTF() method helps in writing the data to be sent.

NOTE: Save the file, if you haven’t saved it already under the name of Client.java.

Creating Server.java

Step 2: Create a new notepad file or you could use the same Server.java to replace its code with the following code:

import java.net.*;
import java.io.*;

public class Server {
public static void main (String []args) {
               try { 
                      ServerSocket ss = new ServerSocket(1999); 
                      Socket s = ss.accept(); 
                      DataInputStream dis = new DataInputStream(s.getInputStream()); 
                      String k = dis.readUTF(); 
                      System.out.println("File Transferred"); 
                      FileOutputStream fos = new FileOutputStream("E:\\roger.txt"); 
                      byte[] b = k.getBytes(); 
                      fos.write(k); 
                     } catch (IOException ie) { 
                       ie.printStackTrace(); 
                     }
          }
}

The job of the server is to keep listening so we add the accept() method. Don’t miss the port no. which should be the same. Then we need to receive data via getInputStream(). The data is read using readUTF() which returns String. You could choose to display the data or opt for showing it in yet another file. I have created roger.txt where the data will be copied. I have made use of FileOutputStream to do that. You could choose your own method to do that.

NOTE: Save the file if you haven’t already with the name Server.java.

Compilation and Execution of Programs

In a manner similar to the one we had seen earlier it is time to compile and run these programs.

Step 3: Open two separate command prompts and compile both the files using the following command:

javac Client.java
javac Server.java

Then press Enter.

Step 4:  Then in one cmd prompt window type:

java Server

and press Enter.

Step 5: Then in another cmd prompt window type:

java Client

and press Enter.

In the form of result you need to manually go and check the roger.txt file that would be created in the same folder.

If you open the file you will see the data of nadal.txt has been really copied into it.

roger notepad file info

Connection-Less Socket Programming in Java

Let’s see the other type of socket programming where there are no acknowledgments made.

A Datagram is nothing but a packet of information. But we don’t know anything about the time it’s going to arrive, or anything about its content.

We make use of DatagramSocket class to send and receive datagram packets. The socket acts as the sending and receiving node for a delivery system. Every packet you receive on the socket is singularly addressed. If there are multiple packets sent to a machine, the routing would be done differently and the packets could arrive in any order.

Constructors of DatagramSocket

Here are the all the constructors that are there in DatagramSocket class:

  1. DatagramSocket()
  2. DatagramSocket(DatagramSocket impl)
  3. DatagramSocket(int port)
  4. DatagramSocket(InetAddress laddr)
  5. DatagramSocket(SocketAddress bindAddr)

Methods like send(), receive(), connect(), getInetAddress(), bind(), disconnect() etc. come really handy when working with the DatagramSocket class.

DatagramPacket Class

DatagramPacket Class represents a data packet. It is nothing but a message that is to be tossed around. Remember the packet delivery is not guaranteed and is quite flaky.

Let’s take a look at its constructors.

Constructors of DatagramPacket Class

  1. DatagramPacket(byte[] buf, int length)
  2. DatagramPacket(byte[] buf, int length, InetAddress address, int port)
  3. DatagramPacket(byte[] buf, int offset, int length)
  4. DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)
  5. DatagramPacket(byte[] buf, int offset, int length, SocektAddress address)
  6. DatagramPacket(byte[] buf, int length, SocektAddress address)

There are all sorts of methods like getPort(), getData(), getLength(), getOffset() etc. to grab data inside the datagram packet.

An example that uses both these classes would be really helpful.

Sending a DatagramPacket (Client Side code)

This part of socket programming in Java is fairly fun.

In order to send a Datagram Packet across you can make use of one of DatagramSocket’s send() methods that takes DatagramPacket instance as an argument.

Here’s the code you should be writing in a notepad file and save it as Client.java.

DatagramSocket ds = new DatagramSocket(); 
InetAddress ip = InetAddress.getByName("localhost"); 
String s = "I am a Datagram info! Woohoo!"; 
DatagramPacket dp = new DatagramPacket(s.getBytes(), s.length(), ip, 9999); 
ds.send(dp); 
ds.close();

It throws SocketException, UnknownHostException, IOException which you need to handle.

Receiving a DatagramPacket (Server Side code)

Receiving a Datagram Packet is fairly simple. All you need to do is use the receive() method of DatagramSocket class.

DatagramSocket ds = new DatagramSocket(9999); 
byte [] b = new byte[30]; 
DatagramPacket dp = new DatagramPacket(b, 30); 
ds.receive(dp); 
System.out.println(new String(b));

Make sure you get the port no. right. It also throws SocketException, UnknownHostException, IOException which you need to handle.

Compilation and Execution of DatagramPacket Program

Now all you have to do is repeat the same process of opening two command prompts and compiling both .java files by their respective names:

javac Client.java

javac Server.java

Press Enter.

Then in one of the command prompt window run Server so that it waits to listen, while in other you run Client.

DatagramPacket message execution in Java

Far easy right?

With that our chapter of socket programming in Java concludes.

Go ahead and try this on two different systems.

Scottshak

Poet. Author. Blogger. Screenwriter. Director. Editor. Software Engineer. Author of "Songs of a Ruin" and proud owner of four websites and two production houses. Also, one of the geekiest Test Automation Engineers based in Ahmedabad.

You may also like...

Leave a Reply