I am using jssc for serial port communication with simulator which I made. The thing is whenever server requests for a device from my simulator I encounter a delay as device in my simulator replies after some time, not exactly after the request. For replying to the request packet I am using jssc method writeBytes() inside the serial event listener which is:
SerialPort.writeBytes(packet);
and the packet is less than 20 bytes and also I am checking my serial event that is
if(event.isRXCHAR() && event.getEventValue() > 0){}
Can you guys help me out to reduce this delay so that simulator device replies just after the request? Here is a piece of code-
public void serialEvent(SerialPortEvent event)
{
if(event.isRXCHAR() && event.getEventValue() > 0)
{
byte Server_PacketByte;
try {
Server_PacketByte = receiver_Port.readBytes(1)[0];
byte[] form_packet = PacketFormation(Server_PacketByte);// for adding bytes to make packet
if(form_packet == null)
{
return;
}
for(Device d : devices)
{
if(form_packet != null)
{
d.processPacket(form_packet);// in the list of devices I have all the information of device and also reply packet
}
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
inside processPacket()
if (packet.equals(REQUEST))
{
receiver_Port.writeBytes(device.getReply());
}
So, I think what's happening with your system is that the response from your simulator back to the server is taking too long, or the server requests are too close together to be useful. If your simulator's response to the server takes too long, then it may disregard or ignore your server's subsequent requests, and your server may handle this by either ignoring the response (since it's for a request it already gave up on) or worse, thinking the response to request #1 is the response to request #3 (which may have had different parameters, and would therefore be invalid).
The solution for this is to either have the server wait a longer amount of time for the response before trying another request, or to somehow reduce the amount of time the simulator needs to respond to the server's request.
If you're just doing an "is device connected" or "get device info"-style request of the device, or one that doesn't require real-time responses, you could have your simulator do that on its own (via a request loop on a separate thread or something) and cache the response, and just hand it back when requested from the server. However, you'd have to make sure that it gets aborted when a real-time request comes through, so it's almost more complicated than necessary.
EDIT: To clarify, I don't think that it's your serial communication that's experiencing an undue delay, because SERIAL COMMUNICATION IS SLOW. I think you haven't considered that fact in your design, and you're expecting all communication for your potentially large number of devices to complete within a certain time frame. In addition, each device may take a variable amount of time to deliver a response back over serial; some of these may not even have flow control implemented properly, resulting in occasional delays or, in rare cases, delivery failures.
You should have some other thread in your Simulator be requesting updates from devices periodically and storing them in a table. That way, when a request comes in from the Server that asks about all devices, their information is already there, and can be packaged and delivered back to the server without the need for serial communication.
Related
This question already has answers here:
Java socket API: How to tell if a connection has been closed?
(9 answers)
Closed 2 years ago.
So I'm in the making of a very simple server/client complex using java. So far I have managed to figure out what happens if the client quits, because then the server receives null while listening from any input from the client.
BUT - what happens if the client is connected and the server quits for any reason... the server is supposed to wait for input from the client, but how can the client know that the server is not listening anymore? For me the clients call to the server just goes into the void... nothing happens...
Can I do something to find out when the server goes down? Time-out, ping/pong or something?
As You surely can see I'm quite new at this, I'm just curious. This was a puzzle for me ever since I attended computer science at the university.
Thanks in advance. dr_xemacs.
(I am assuming you are working with blocking server socket and socket and not with non blocking ones)
Similarly to the server, reading from streams of a closed connection will return null.
However if you instead do not want to rely on this or a scared that the connection to the server could somehow persist, you can also use time outs (check this out! ) which will throw SocketTimeoutException when the time is up and, to keep track of whether the server is up or not, create a ping/packet to assure server is still up and running.
Edit: I did a quick search and this could be useful to you! Take a look!
How can the client know that the server is not listening anymore?
If the client doesn't attempt to interact at some level with the service, it won't know.
Assuming that the client has sent a request, a few different scenarios.
If the service is no longer listening on the designated port, the client will typically get a "Connection Refused" exception.
If the service is still running (in a sense) but it is not working properly, then connection attempts from the client are likely to time out.
If the service's host is down, the client liable get a timeout.
If there are network connectivity or firewall issues, the client could get a timeout or some other exception.
Can I do something to find out when the server goes down? Time-out, ping/pong or something?
You attempt to connect and send a request. If it fails or times out, that means the service is down. If you are designing and implementing the service yourself, you could include a special "healthcheck" request for clients to "ping" on. But the flip-side is that network and server resources will be consumed in receiving and responding to these requests. It can affect your ability to scale up the number of clients, for example, if each client pings the service every N seconds.
But a client typically doesn't need to know whether the service is up or down. It typically only cares that service responds when it it sends a real request. And the simplest way to handle that is to just send the request and deal with the outcome. (The client code has to deal with all possible outcomes anyway when doing a real request. The service can go down, etc between the last healthcheck ping and when the client sends a real request.)
Bottom line: Don't bother with checking availability in the client unless the application (i.e. the end user) really needs to know.
Your Server probably may be running on a certain port and so you can add a health check at the client side and update a global flag with status to let client know about its availibity :-
Socket socket = null;
try
{
socket = new Socket(host, port);
return true;
}
catch (Exception e)
{
return false;
}
finally
{
if(socket != null)
try
{
socket.close();
}
catch(Exception e){}
}
Currently have a TCP server built in Java and I'm sending messages/packets out to clients using their socket's OutputStream:
// Send all player's information to everyone else
outerPlayerIter = players.iterator();
while(outerPlayerIter.hasNext()) {
Player outerPlayer = outerPlayerIter.next();
Iterator<Player> innerPlayerIter = players.iterator();
while(innerPlayerIter.hasNext()) {
Player innerPlayer = innerPlayerIter.next();
boolean isYou = false;
if(innerPlayer.equals(outerPlayer)) isYou = true;
// Send innerPlayer's info to outerPlayer
Thread.sleep(100);
dataBuffer.clearBuffer();
dataBuffer.writeByte(Msgs.mm_toclient.MES_SENDPLAYERINFO);
dataBuffer.writeBool(isYou);
dataBuffer.writeBool(innerPlayer.getIsHost());
dataBuffer.writeString(innerPlayer.getName());
dataBuffer.writeString(innerPlayer.getPublicIP().getHostAddress());
dataBuffer.writeShort((short)innerPlayer.getUdpPort());
outerPlayer.getSocket().getOutputStream().write(dataBuffer.getByteArray());
outerPlayer.getSocket().getOutputStream().flush();
}
}
However, sometimes the clients don't appear to receive all the messages. I can't send multiple messages at the exact same time over one socket.
One way to temporarily fix this was to sleep before I send another packet out. But I'm not sure why this is needed.
Am I doing something wrong in regards to how I'm sending/writing the packets out to be sent? What can be fixed to allow multiple packets to be received correctly at once without sleeping?
It might be due to the fact that the client closes the socket way too fast before the communication should actually finished. Could you please try to bump up the thread.sleep value or, on the client side, if you use any kind of timing, try to bump up that one as well.
I need to implement a heartbeat system on my Java project (3-5 Clients with 1 server for them) but I have some questions.
1) Do I need to have 2 sockets by clients ? 1 for the heartbeat and 1 to receive normal message for my software
2) I saw that in specific case when a client is lagging, the client don't receive a message, how to avoid this ?
3) In case of a client disconnect, how to retreive the connection with it ? Without recreate a new socket with it.
So, you have a "central server" which needs to provide an heartbeat mechanism to the clients. Well, part of the solution is simple since you have only 1 server, which simplifies a LOT since you don't need to deal with data replication, data synchronization mechanisms, server failure, and so on. You just expect that your server never fails and if it fails it's a fatal error.
My suggestion is to implement a system based on notifications (pooling is bad and ugly): instead of having the server pooling the clients, you have the clients reporting to the server every X seconds of their state. This reduces the general overload of your system and it's based on the design principle of "Tell, don't ask". This also allows you to have different report times for each individual client.
There is one more question, which is what data do you want to transmit? Simply if the client is alive? Runtime data of the client, for example, % of it's job done if the client is downloading a file? Environment status, such as CPU overload, memory usage, network status? Define that, that's the first step.
Talking about the java implementation, you should run your a thread on each of your clients (implementing the Runnable interface). It should look something like this code (this is simplified for the sake of brevity):
public class HeartbeatAgent implements Runnable {
private int DEFAULT_SAMPLING_PERIOD = 5; //seconds
private String DEFAULT_NAME = "HeartbeatAgent";
private HashMap<Integer, Object> values; // <id, value>
public HeartbeatAgent () {
values = new HashMap<Integer,Object>();
}
private void collect() {
/** Here you should collect the data you want to send
and store it in the hash
**/
}
public void sendData(){
/** Here you should send the data to the server. Use REST/SOAP/multicast messages, whatever you want/need/are forced to **/
}
public void run() {
System.out.println("Running " + DEFAULT_NAME );
try {
while( /** condition you want to stop **/ {
System.out.println("Thread: " + DEFAULT_NAME + ", " + "I'm alive");
this.collect();
this.send();
// Let the thread sleep for a while.
Thread.sleep(DEFAULT_SAMPLING_PERIOD * 1000);
}
} catch (InterruptedException e) {
System.out.println("Thread " + DEFAULT_NAME + " interrupted.");
}
System.out.println("Thread " + DEFAULT_NAME + " exiting.");
}
}
You should write a server that handles the requests made and is "smart" enough to call a time-out after X seconds without "news" from client Y.
This is still not ideal, since you collect data and send it with the same sampling period, but usually you want to collect data at very tiny intervals (collecting CPU usage every 5 seconds, for instance) but only report it every 30 seconds.
If you want to look at good code of a good library that does this (it's what we've been using to our project at my company), take a look at JCatascopia framework code (just look at the Agent and Server folders, ignore the others).
There's a lot to say about this topic, this is the basic. Feel free to ask!
You could try to take a look at this small framework I made for a project I'd worked one last year. It's focused on a simple implementation and yet a strong feedback about your clients status.
It's based on UDP protocol which sends a payload containg an id, which it can be a MAC address of a NIC or an id chosen and set automatically by you or something else too, that confirms the client being safe and sound.
I think it's kind of cool because it's based on listeners which then receive various kinds of events based on what the heartbeat protocol compute about a client status.
You can find more about it here
I think it's handy to use it with TCP sockets to understand if you are capable or not to send data over your TCP stream. Having continuos feedback on your clients status takes you in a position where you can easily achieve that, for example by saving in some sort of map your client status and check it before sending any kind of data.
Ok. I'm trying to grasp some multithreading Java concepts. I know how to set up a multiclient/server solution. The server will start a new thread for every connected client.
Conceptually like this...
The loop in Server.java:
while (true) {
Socket socket = serverSocket.accept();
System.out.println(socket.getInetAddress().getHostAddress() + " connected");
new ClientHandler(socket).start();
}
The ClientHandler.java loop is:
while(true)
{
try {
myString = (String) objectInputStream.readObject();
}
catch (ClassNotFoundException | IOException e) {
break;
}
System.out.println(myClientAddress + " sent " + myString);
try {
objectOutputStream.writeObject(someValueFromTheServer);
objectOutputStream.flush();
}
catch (IOException e) {
return;
}
}
This is just a concept to grasp the idea. Now, I want the server to be able to send the same object or data at the same time - to all clients.
So somehow I must get the Server to speak to every single thread. Let's say I want the server to generate random numbers with a certain time interval and send them to the clients.
Should I use properties in the Server that the threads can access? Is there a way to just call a method in the running threads from the main thread? I have no clue where to go from here.
Bonus question:
I have another problem too... Which might be hard to see in this code. But I want every client to be able to receive messages from the server AND send messages to the sever independently. Right now I can get the Client to stand and wait for my gui to give something to send. After sending, the Client will wait for the server to send something back that it will give to the gui. You can see that my ClientHandler has that problem too.
This means that while the Client is waiting for the server to send something it cannot send anything new to the server. Also, while the Client is waiting for the gui to give it something to send, it cannot receive from the server.
I have only made a server/client app that uses the server to process data it receives from the Client - and the it sends the processed data back.
Could anyone point me in any direction with this? I think I need help how to think conceptually there. Should I have two different ClientHandlers? One for the instream and one for the outstream? I fumbling in the dark here.
"Is there a way to just call a method in the running threads from the main thread?"
No.
One simple way to solve your problem would be to have the "server" thread send the broadcast to every client. Instead of simply creating new Client objects and letting them go (as in your example), it could keep all of the active Client objects in a collection. When it's time to send a broadcast message, it could iterate over all of the Client objects, and call a sendBroadcast() method on each one.
Of course, you would have to synchronize each client thread's use of a Client object outputStream with the server thread's use of the same stream. You also might have to deal with client connections that don't last forever (their Client objects must somehow be removed from the collection.)
I have an application where I am receiving information from a server and then showing that information on the screen for the user. Since there is a lot of information, I would like to update the UI as I receive the information.
Sending/Receiving is done on a separate thread.
Two questions:
How can I best receive multiple UDP packets?
My current code for receiving one packet
try {
Log.i(TAG,"Listening...");
_dcOut.setSoTimeout(20000);
_dcOut.receive(packet);/* Wait to receive a datagram */
haveDatagram = true;
Log.d(TAG,"dc_out, received...");
}
catch (Exception e) { // can be just a time out
haveDatagram = false;
Log.d(TAG,"dc_out, failed to receive...");
}
Is it possible to update UI while receiving multiple UDP packets?
Edit:
I am using a bound service to get the information from the server(AIDL to be specific). Here is the setup:
Either I:
1. get an individual object and send it back and that's that for that particular instance of the service or
2. I can send back a List of them for that service
My idea is that I should send back a list of say, 5-10 objects, and repeat that for a while?
--I feel like there isn't a way for me to be updating the UI while receiving the packets with this service setup--
If the receiving of UDP packets are done on a seperate thread, there should be no problems showing it on your GUI!
Your code shows only receving UDP data. I need more info to be specific :)
Only one UDPSocket handles incoming data on a specific port, they will all (packets) be stored sequentially in a buffer, dedicated to that specific process.