Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficiency Issue in the following data transfer technique via Socket communication

Tags:

java

sockets

I've been facing this issue for very long time to implement the following scenario with a good practice. And I'm having issues. Suggest me or guide me if I went wrong somewhere. Details as follows.

1) I've a PLC that acts as a server socket program. And I have a Java Client Socket program to read the data from the Server.

Since here PLC is the Server, It establishes a passive communication and when the client initiates the communication, Server provides client the data from a specific area which look the below Kishore Kumar Korada

As you can see in the image, For each read, Client program should get all the data from first byte to last byte from the Server Sending area. And as per the offset and length that Client program was provided, It process the data and store it into the database.

Note: Each time, Client program should get the similar data with same offsets and length.

2) I unsure of if I could achieve this with a single socket connection(Tried but didn't get expected result), was reading the data from the server, processing it, storing it in db then Closing the Socket. And Re-creating the socket again. And I'm doing this in every 1 second interval. Which means I'm creating a lot of sockets.
Overall structure can be descried pictorially as below Kishore Kumar Korada
3) Client code I've used to get the data from the server is below

try {
    socket = new Socket(host, port);
    is = socket.getInputStream();
    outputBuffer = new ByteArrayOutputStream();

    byte[] buffer = new byte[1024];
    int read;
    if((read = is.read(buffer)) != -1) {
        outputBuffer.write(buffer, 0, read);
    }
    /* All Processing work */
} catch (UnknownHostException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} catch (Exception e) {
    e.printStackTrace();
} finally {
    try {
        System.out.println("Before closing the socket");
        try {
            is.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("After closing the socket");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

I'm closing the sockets as you can see here. And I've been running the same code snippet for every second in a scheduler.

By having all this structure, I would like to ask following questions
1) Can I get the same data as you can see in the first picture with a single socket connection every time when it gets enabled for me to read??? If yes, Could be explain briefly?
2) Is my Code snippet looks as a Client Socket Program? I know I've closed the socket in there. Actually like I said before, I've been executing the same code for every 1 second. If it's not a good practice, Could you suggest me one?
3) Over all, by looking into the second picture, how to achieve the same data from sending area again and again with same offset?

like image 552
Kishore Kumar Korada Avatar asked Feb 06 '19 11:02

Kishore Kumar Korada


People also ask

Why do socket programs need to be divided into separate messages?

Most applications are not that simple and usually require that the stream can be divided into a number of distinct messages. A message exchanged between two socket programs must imbed information so that the receiver can decide how many bytes to expect from the sender and (optionally) what to do with the received message.

How many clients can a socket communication handle?

In the development environment the socket communications are functional automatically for testing 5 clients at the most. 1st TCP protocol that enables to transfer the unlimited size of data as well as to check the correct sequence and to control the data and the connection.

What is the purpose of socket communication?

The socket communication serves first of all for a data exchange between applications in the network. The model client-server is used for the communication in the network.

What happens when a program receives data from a stream?

The receiving program reads whatever data is on the stream and then loops through the received buffer separating each record at the point where a null-byte is found. When the received records have been processed, the program issues a new read for the next block of data on the stream.


1 Answers

1) Can I get the same data as you can see in the first picture with a single socket connection every time when it gets enabled for me to read??? If yes, Could be explain briefly?

You can, but I wouldn't recommend it. Because you're receiving a fixed amount of data every second and processing it immediately after, I would opt to have one thread tasked with reading the data from the socket, and another thread (or pool of threads) tasked with processing the incoming data. If processing the data takes longer than one second and you process it on the same thread as the Socket, data will become backed up very quickly.

2) Is my Code snippet looks as a Client Socket Program? I know I've closed the socket in there. Actually like I said before, I've been executing the same code for every 1 second. If it's not a good practice, Could you suggest me one?

Client/Server programs can vary in many ways, so there's no correct standard. Regarding alternative solutions, see what I wrote above.

3) Over all, by looking into the second picture, how to achieve the same data from sending area again and again with same offset?

Luckily for you, I created and maintain a client/server framework called SimpleNet, which I think would make this a lot easier!

Example code for your program using SimpleNet would look like the following:

Client client = new Client();

client.onConnect(() -> {
    // Continuously read 52 bytes of data and invoke the callback when they arrive.
    client.readAlways(52, buffer -> {
        int realValue = buffer.getInt();  // 4 bytes
        int intValue = buffer.getShort(); // 2 bytes

        byte[] operatorNameBytes = new byte[18];
        buffer.get(operatorNameBytes);
        String operatorName = new String(operatorNameBytes);

        byte[] shiftIdBytes = new byte[10];
        buffer.get(shiftIdBytes);
        String shiftId = new String(shiftIdBytes);

        byte[] productIdBytes = new byte[16];
        buffer.get(productIdBytes);
        String productId = new String(productIdBytes);

        int status = buffer.getShort(); // 2 bytes

        // All processing work can occur here or be delegated to a thread pool.
    });
});

client.connect(host, port);

By keeping the connection to the server open, I think it would end up being less expensive than having to constantly create and destroy Socket objects. Also, the asynchronous callbacks that SimpleNet uses should enable it to be scalable if you ever decide to send more data in.

Note: Assuming that your server sends data to the client once per second, then the example will work for you without having to change anything. Otherwise, you can change client.readAlways to client.read and use a ScheduledExecutorService to invoke client.read once per second. If your server only sends data to a client when they first connect, then you can also use client.read and just reconnect the client once per second.

like image 114
Jacob G. Avatar answered Oct 19 '22 02:10

Jacob G.