Home > Software design >  Java socket write issues
Java socket write issues

Time:11-08

I am trying to create a Modbus setup as follows:

client <----> IED <----> Modbus Server

IED has the IP 192.168.x.x and Modbus Server uses localhost as IP. All entities are in the same VM. The client is supposed to send a request to the IED,the IED forwards it to the server and the server responds to the IED.

The problem is the IED receives the request from the master which is stored in a byte array but transmitting the request to the server does not work. Wireshark traces show that the TCP connection is established with the server but request is not transmitted.

See the code below:

public class App {
    public static void main(String[] args) {
        IEDServer iedServer = new IEDServer();
        iedServer.start(502);
    }    
}

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

public class IEDServer {
    private ServerSocket serverSocket;

    public void start (int port){
        try {
            InetAddress inetAddress = InetAddress.getByName("192.168.20.138");
            serverSocket = new ServerSocket(port, 1024, inetAddress);
            while (true){
                new ClientHandler(serverSocket.accept()).start();
                System.out.println("Connection accepted");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void stop(){
        try {
            serverSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

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

public class ClientHandler extends Thread{
    private Socket clientSocket;

    private DataOutputStream out;
    private DataInputStream in;


    public ClientHandler(Socket clientSocket) {
        this.clientSocket = clientSocket;
    }

    @Override
    public void run() {
        try {
            //connection from client
            out = new DataOutputStream (clientSocket.getOutputStream());
            in = new DataInputStream(clientSocket.getInputStream());
//            in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
//            String readline;

            //for connection to modbus server
            Socket modbusSocket = new Socket("127.0.0.1",502);
            modbusSocket.setSoTimeout(10000);
            DataOutputStream modbus_out = new DataOutputStream (clientSocket.getOutputStream());
            DataInputStream modbus_in = new DataInputStream(clientSocket.getInputStream());
            byte [] modbus_bytes = {};

            //read Modbus bytes from client to get client request
            modbus_bytes = in.readAllBytes();

            System.out.println("Modbus request: ");
            for (byte b: modbus_bytes){
                System.out.print(b);
            }
            System.out.println();

            //transfer modbus request to modbus server
            modbus_out.write(modbus_bytes, 0, modbus_bytes.length);

            //get response from modbus server
            modbus_bytes = modbus_in.readAllBytes();

            System.out.println("Modbus response: ");
            for (byte b: modbus_bytes){
                System.out.print(b);
            }
            System.out.println();

            //transfer response to client
            out.write(modbus_bytes,0,modbus_bytes.length);

        } catch (IOException e) {
            e.printStackTrace();
        }

        //close TCP connection
        try {
            in.close();
            out.close();
            clientSocket.close();
            System.out.println("Connection terminated");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("Connection termination failed");
        }
    }
}

Also find below, the wireshark screenshot Wireshark Trace

CodePudding user response:

Call DataOutputStream.flush() after DataOutputStream.write() to force the bytes to be send

CodePudding user response:

I managed to fix it. I mistakenly passed clientSocketinstead of modbusSocketas a parameter to the modbus_inand modbus_outStream instances. I also had to poll for availability of data before reading and then writing. Also, I noticed that the client-side closed the TCP session while the server-side had it open. So I ensured that the connection was closed after each query.

Please find modified code below for ClientHandler:

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

public class ClientHandler extends Thread {
    private Socket clientSocket;
    private Socket modbusSocket;

    private DataOutputStream out, modbus_out;
    private DataInputStream in, modbus_in;

    public ClientHandler(Socket clientSocket) {
        this.clientSocket = clientSocket;
        System.out.println(clientSocket.getInetAddress());

        try {
            out = new DataOutputStream(new BufferedOutputStream(clientSocket.getOutputStream()));
            in = new DataInputStream(new BufferedInputStream(clientSocket.getInputStream()));

//            in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
//            String readline;

            //for connection to modbus server
            modbusSocket = new Socket("127.0.0.1", 502);
            //            modbusSocket.setSoTimeout(10000);
            modbus_out = new DataOutputStream(new BufferedOutputStream(modbusSocket.getOutputStream()));
            modbus_in = new DataInputStream(new BufferedInputStream(modbusSocket.getInputStream()));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        try {
            //connection from client
            if (in.available() > 0) {
                //read Modbus bytes from client to get client request
                System.out.println("===============Begin reading===============");
                byte[] modbus_bytes = new byte[in.available()];
                in.read(modbus_bytes);
                System.out.println("Modbus request: ");
                for (byte b : modbus_bytes) {
                    System.out.print(b);
                }
                System.out.println();

                //transfer modbus request to modbus server
                modbus_out.write(modbus_bytes);
                modbus_out.flush();
                System.out.println("Written to modbus server");

                while (modbus_in.available() == 0) {
                    System.out.println("Waiting for device response...");
                }
                System.out.println("\nDevice response ready");

                //get response from modbus server
                modbus_bytes = new byte[modbus_in.available()];
                modbus_in.read(modbus_bytes);

                System.out.print("Modbus response: ");
                for (byte b : modbus_bytes) {
                    System.out.print(b);
                }
                System.out.println("\nSending response to client");

                //transfer response to client
                out.write(modbus_bytes);
                out.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        //close TCP connection
        try {
//            in.close();
//            out.close();
            clientSocket.close();
            modbusSocket.close();
            System.out.println("===========Connection terminated==============");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("Connection termination failed");
        }
    }
}
  • Related