Creating a Simple Java TCP/IP Server and Client Socket

In this example, 2 simple Java TCP/IP server and client socket applications are created. One for sending character data over a TCP/IP socket connection and another one for sending binary data –an image is used-, over a TCP/IP socket connection. Java SE 8 and the Eclipse Neon setup from the post below were used.

The Java APIs for socket programming are part of the Java SE (Standard Edition). See java.io and java.net.

Related Posts

Summary

  1. Implementation of Server Socket in Java
  2. Implementation of Client Socket in Java
  3. Running the Server Socket and Client Socket
  4. Monitoring TCP/IP Network Traffic using Wireshark
  5. Sending Binary Data such as an Image over TCP/IP Socket Connection

1  Implementation of Server Socket in Java

  • Below is the Java source code for the server socket implementation.
  • The server socket is created in line 15 or line 17. See java.net.ServerSocket for more information.
package com.pgx.java.socket;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class MyServerSocket {

    private ServerSocket server;

    public MyServerSocket(String ipAddress) throws Exception {
        if (ipAddress != null && !ipAddress.isEmpty()) 
          this.server = new ServerSocket(0, 1, InetAddress.getByName(ipAddress));
        else 
          this.server = new ServerSocket(0, 1, InetAddress.getLocalHost());
    }

    private void listen() throws Exception {
        String data = null;
        Socket client = this.server.accept();
        String clientAddress = client.getInetAddress().getHostAddress();
        System.out.println("\r\nNew connection from " + clientAddress);
        
        BufferedReader in = new BufferedReader(
                new InputStreamReader(client.getInputStream()));        

        while ( (data = in.readLine()) != null ) {
            System.out.println("\r\nMessage from " + clientAddress + ": " + data);
        }
    }

    public InetAddress getSocketAddress() {
        return this.server.getInetAddress();
    }
    
    public int getPort() {
        return this.server.getLocalPort();
    }

    public static void main(String[] args) throws Exception {
        MyServerSocket app = new MyServerSocket(args[0]);

        System.out.println("\r\nRunning Server: " + 
                "Host=" + app.getSocketAddress().getHostAddress() + 
                " Port=" + app.getPort());
        
        app.listen();
    }
}

The Constructor in this class:

Uses java.net.ServerSocket to create a new TCP/IP server socket using the provided ipAddress argument. If that argument is null or empty, it will try to resolve the local hosts’s IP address automatically. You may want to specify the server’s IP address if you have multiple network interfaces. The class java.net.InetAddress is used to set the IP address of the server socket. The local host address is used as an input parameter for the ServerSocket constructor.

2  Implementation of Client Socket in Java

  • Below is the Java source code for the client socket implementation.
  • The client socket is created in line 15. See java.net.Socket for more information.
package com.pgx.java.socket;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;

public class MyClientSocket {

    private Socket socket;
    private Scanner scanner;

    private MyClientSocket(InetAddress serverAddress, int serverPort) throws Exception {
        this.socket = new Socket(serverAddress, serverPort);
        this.scanner = new Scanner(System.in);
    }

    private void start() throws IOException {
        String input;

        while (true) {
            input = scanner.nextLine();

            PrintWriter out = new PrintWriter(this.socket.getOutputStream(), true);
            out.println(input);
            out.flush();
        }
    }
    
    public static void main(String[] args) throws Exception {
        MyClientSocket client = new MyClientSocket(
                InetAddress.getByName(args[0]), 
                Integer.parseInt(args[1]));
        
        System.out.println("\r\nConnected to Server: " + client.socket.getInetAddress());
        client.start();                
    }
}

The Constructor in this class:

Requires the socket server’s IP address and the port number as arguments for opening a new socket connection to the server using the java.net.Socket class. It then uses the java.util.Scanner class to read keyboard input and to send the input as character data over the socket connection to the server.

3  Running the Java TCP/IP Server and Client Socket Application

  • Here, the Java TCP/IP server and client socket application is exported to an executable JAR file named TCPSocketTest.jar. For a quick description on how to create a JAR file in Eclipse, see:
  • Here, the server socket application will run on a machine with IP address 192.168.0.15.
  • Here, the client socket application will run on a machine with IP address 192.168.0.14.

3.1 Start the Server Socket Application

  • To run the server socket from a terminal or Windows command prompt, use the java command:
  java -cp TCPSocketTest.jar com.pgx.java.socket.MyServerSocket
  • When the server socket is running, it will print the host name (IP Address) and the socket port number.

MyMac:Java root$ ls
TCPSocketTest.jar
MyMac:Java root$ java -cp TCPSocketTest.jar com.pgx.java.socket.MyServerSocket

Running Server: Host=192.168.0.15 Port=53257
 
  • The socket port, here 53257, is given by the operating system and set automatically.
  • See line 17 in the MyServerSocket code and java.net.ServerSocket for more information.
  • The server socket is now ready to accept client connections.

3.2 Start the Client Socket Application

  • To run the client socket from a terminal or Windows command prompt, use the java command:
  java -cp TCPSocketTest.jar com.pgx.java.socket.MyClientSocket 192.168.0.15 53257
  • Where the first input argument is the server’s IP address and the second one is the port number.

MyMac2:Java root$ ls
TCPSocketTest.jar
MyMac2:Java root$ java -cp TCPSocketTest.jar com.pgx.java.socket.MyClientSocket 192.168.0.15 53257

Connected to Server: /192.168.0.15
 
  • The server socket application will print a message when a new client connection is opened:

MyMac:Java root$ ls
TCPSocketTest.jar
MyMac:Java root$ java -cp TCPSocketTest.jar com.pgx.java.socket.MyServerSocket

Running Server: Host=192.168.0.15 Port=53257

New connection from 192.168.0.14
 

3.3 Send a Message

  • In the client socket application, type a message and press ENTER.

MyMac2:Java root$ ls
TCPSocketTest.jar
MyMac2:Java root$ java -cp TCPSocketTest.jar com.pgx.java.socket.MyClientSocket 192.168.0.15 53257

Connected to Server: /192.168.0.15
Hello from the client!

  • The server socket application, will print the message that was received from the client.

MyMac:Java root$ ls
TCPSocketTest.jar
MyMac:Java root$ java -cp TCPSocketTest.jar com.pgx.java.socket.MyServerSocket 192.168.0.15

Running Server: Host=192.168.0.15 Port=53257

New connection from 192.168.0.14

Message from 192.168.0.14: Hello from the client!
 
  • The Java server and client applications can be stopped by pressing CTRL + C.

4  Monitoring TCP/IP Network Traffic using Wireshark

Wireshark Download Page - Download Stable Release for Mac OS 10.6 and Later
  • After installation, run Wireshark and select a network interface to capture traffic on.
  • Here, the localhost’s Loopback interface lo0 is selected to monitor local traffic.
Wireshark - Select Network Interface for Traffic TCP/IP Capture
  • In the green filter field, enter the below pattern to filter the traffic by the server socket TCP port:
tcp.port == 53257
  • Send messages from the client- to the server socket to capture traffic.
  • To view the payload of a TCP packet, expand the Data node and click on the [Length: ..] item.
Wireshark - Capturing Java TCP/IP Server and Client Socket Traffic on Loopback Interface

5  Sending Binary Data such as an Image over TCP/IP Socket Connection

In the previous example, text data messages are sent through the TCP/IP socket connection. In this section, it is shown how to send binary data such as an image with a Java TCP/IP server and client socket application. The below image from the Porsche Media Gallery is used here:

Sample Image - Blue 2018 Porsche Carrera Cabriolet GTS

5.1 Implementation of TCP/IP Socket Client (Binary)

  • The client will read the image file from its file system and then send the binary data through the socket.
  • The below code shows a new socket program, called MyClientSocketBinary which uses a class named MyFileReader to read an image file and then send its binary data over a socket connection.
package com.pgx.java.socket;

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;

public class MyClientSocketBinary {

    private Socket socket;
    private MyFileReader fileReader;

    private MyClientSocketBinary(InetAddress serverAddress, int serverPort) throws Exception {
        this.socket = new Socket(serverAddress, serverPort);
    }
    
    private void sendFile(String fileName) throws IOException {
        //
        // Read file from disk
        //
        fileReader = new MyFileReader();
        byte[] data = fileReader.readFile(fileName);

        //
        // Send binary data over the TCP/IP socket connection
        //
        for (byte i : data) {
            this.socket.getOutputStream().write(i);    
        }
        
        System.out.println("\r\nSent " + data.length + " bytes to server.");
    }    

    /**
     * Requires 3 arguments:
     *     1: TCP/IP server host name or IP address
     *     2: TCP/IP server port number
     *     3: Absolute path and file name of file to send
     *     
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {                        
        MyClientSocketBinary client = new MyClientSocketBinary(
                InetAddress.getByName(args[0]), 
                Integer.parseInt(args[1]));

        System.out.println("\r\nConnected to Server: " + client.socket.getInetAddress());
        client.sendFile(args[2]);
    }
}
package com.pgx.java.socket;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class MyFileReader {

    public byte[] readFile(String fileName) throws IOException {
        File file = new File(fileName);
        byte[] fileData = new byte[(int)file.length()];
        BufferedInputStream br = new BufferedInputStream(new FileInputStream(file)); 
        
        int bytesRead = 0;
        int b;

        while ((b = br.read()) != -1) {
            fileData[bytesRead++] = (byte)b;
        }
        
        br.close();
        return fileData;
    }
    
    /**
     * For testing:
     *    args[0] = Name of binary file to read into memory.
     */
    public static void main(String[] args) throws IOException {
        //
        // Read file into byte array and print its size
        //
        byte[] data = new MyFileReader().readFile(args[0]);
        System.out.println("size: " + data.length);
    }
}
  • The main method is for testing here. It reads the contents of a file and prints the number of bytes read.

5.2 Implementation of TCP/IP Socket Server (Binary)

  • The modified version of the server, named MyServerSocketBinary reads the incoming binary data from the socket connection and then writes it to a JPEG file on its file system disk using a class named MyFileWriter.
package com.pgx.java.socket;

import java.io.BufferedInputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class MyServerSocketBinary {

    private ServerSocket server;

    public MyServerSocketBinary(String ipAddress) throws Exception {
        if (ipAddress != null && !ipAddress.isEmpty()) 
            this.server = new ServerSocket(0, 1, InetAddress.getByName(ipAddress));
        else 
            this.server = new ServerSocket(0, 1, InetAddress.getLocalHost());
    }

    private void listen() throws Exception {
        MyFileWriter fw = new MyFileWriter();

        //
        // Accept new client connection
        //
        Socket client = this.server.accept();
        String clientAddress = client.getInetAddress().getHostAddress();
        System.out.println("\r\nNew connection from " + clientAddress);

        //
        // Read binary data from client socket and write to file
        //
        BufferedInputStream bis = new BufferedInputStream(client.getInputStream());        
        String fileName = "image-" + System.currentTimeMillis() + ".jpg";
        int fileSize = fw.writeFile(fileName, bis);
        bis.close();
        
        //
        // Close socket connection
        //
        client.close();
        System.out.println("\r\nWrote " + fileSize + " bytes to file " + fileName);
    }

    public InetAddress getSocketAddress() {
        return this.server.getInetAddress();
    }

    public int getPort() {
        return this.server.getLocalPort();
    }

    public static void main(String[] args) throws Exception {
        MyServerSocketBinary app = new MyServerSocketBinary(args[0]);
        
        System.out.println("\r\nRunning Server (Image): " + 
                "Host=" + app.getSocketAddress().getHostAddress() + 
                " Port=" + app.getPort());
        
        app.listen();
    }
}
  • The Java source code of MyFileWriter is shown below.
package com.pgx.java.socket;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class MyFileWriter {
    
    public int writeFile(String fileName, InputStream inputStream) throws IOException {
        File f = new File(fileName);
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(f));
        int bytesWritten = 0;
        int b;

        while ((b = inputStream.read()) != -1) {
            bos.write(b);
            bytesWritten++;
        }

        bos.close();
        
        return bytesWritten;
    }

    /**
     * For testing:
     *    args[0] = Name of binary file to make a copy of.
     */
    public static void main(String[] args) throws Exception {
        // 
        // Read file
        //
        MyFileReader mfr = new MyFileReader();
        String fileName = args[0];
        byte[] fileData = mfr.readFile(fileName);

        // 
        // Write copy of file
        //
        String[] parts = fileName.split("\\."); 
        InputStream is = new ByteArrayInputStream(fileData);
        new MyFileWriter().writeFile(fileName + "_COPY." + parts[1], is);
    }
}
  • The main method is for testing here. It reads the contents of a file and creates an identical copy of it.

5.3 Start the MySocketServerBinary Program

  • The binary socket server program is started on a machine with IP address 192.168.56.1.

MyMac:Java root$ ls
TCPSocketTest.jar
MyMac:Java root$ java -cp TCPSocketTest.jar com.pgx.java.socket.MyServerSocketBinary 192.168.56.1

Running Server: Host=192.168.56.1 Port=62764
 

5.4 Start the MySocketClientBinary Program

  • The binary socket client program is started on a machine with IP address 192.168.56.2.
  • The image file to send is located in the same folder as the TCPSocketTest.jar file.

MyMac2:Java root$ ls
TCPSocketTest.jar SAPHIRE_BLUE_CARRERA_CABRIOLET_GTS_017.jpg
MyMac2:Java root$ java -cp TCPSocketTest.jar com.pgx.java.socket.MyClientSocketBinary 
 192.168.56.1 53257 saphire_blue_carrera_cabriolet_gts_017.jpg

Connected to Server: /192.168.56.1

Sent 11032590 bytes to server.

MyMac2:Java root$ 
  • The above console shows the output when running the client. It will read the file, send its contents over the socket connection, then close the socket and exit the program.
  • The server will read the incoming binary data, write it to a file named image-<TIMESTAMP>.jpg and then exit.

MyMac:Java root$ ls
TCPSocketTest.jar
MyMac:Java root$ java -cp TCPSocketTest.jar com.pgx.java.socket.MyServerSocketBinary 192.168.56.1

Running Server: Host=192.168.56.1 Port=62764

Wrote 11032590 bytes to file image-1519851283392.jpg

MyMac:Java root$
 
  • View the image on the server side machine to confirm it opens correctly. Or use Get Info in Finder on Mac OS to view the meta data of the received JPG file (if it can’t be viewed / read, the JPG file is corrupted).
View JPG Image Metadata and Preview using Mac OS Finder Get Info

2 thoughts on “Creating a Simple Java TCP/IP Server and Client Socket

  1. on client one
    Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 0
    at Client.main(Client.java:21)

    on server one
    Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 0
    at Socket.main(Socket.java:40)

    • Hello,

      it seems that you are not passing any arguments when running both the server and the client. See section 3 on running the server and client. For example, the server is started using:
      java -cp TCPSocketTest.jar com.pgx.java.socket.MyServerSocket 192.168.0.15 where 192.168.0.15 is the only input argument which is accessed in the main method with args[0]. If you don’t pass that argument, the args[] array will be empty and you get the ArrayIndexOutOfBoundsException when trying to read from it.

Leave a Reply