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.
Related
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 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.
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'm new to socket programming and programming a Java UDP simple client-server application. I'm writing a time/date server client. The client can ask the server for the time and date and it waits for a response. Also, every minute, the server updates all clients with the current time. The client needs to
be able to initiate contact with the server and wait for a message back
listen for periodic updates from the server
How can I do this using a single DatagramSocket?
I was thinking of creating two threads: one that listens and one that writes. The problem is that in the case that the client initiates contact with the server, it needs to wait to receive an acknowledgement from the server. So, the writing thread also needs to listen for packets from the server sometimes. But in this case, I have two threads listening and the wrong thread will get the acknowledgement.
Is there a way to specify which thread gets the input? Or is there some other way to solve this problem?
I've been searching for this answer but unable to find it. The closest I've found is Java sockets: can you send from one thread and receive on another?
If there is just one writer thread then it could send the request and go into a wait loop. The listener thread would then get the response, add it to a shared variable (maybe an AtomicReference), and then notify the writer that response has been received.
// both write and listener threads will need to share this
private final AtomicReference<Response> responseRef =
new AtomicReference<Response>();
...
// writer-thread
writeRequest(request);
synchronize (responseRef) {
while (responseRef.get() == null) {
// maybe put a timeout here
responseRef.wait();
}
}
processResponse(response);
...
// listener-thread
Response response = readResponse();
synchronize (responseRef) {
responseRef.set(response);
responseRef.notify();
}
If you have multiple writers or multiple requests being sent at the same time then it gets more complicated. You'll need to send some sort of unique id with each request and return it in the response. Then the response thread can match up the request with the response. You'd need a ConcurrentHashMap or other shared collection so that the responder can match up the particular request, add the response, and notify the appropriate waiting thread.
I have made an client - server example using netty.
I have defined handlers for the server and the client.
Basically I connect with the client to the server and send some messages.
Every received message gets send back (with the content of the message being converted to upper case).
All the work on the received messages, on server and client-side, is done by the defined handlers.
But I would like to use, or better receive/accept, some of the messages directly in the client
not (just) in the handler. So my question is is it possible to have some listener to receive messages directly in the client-program and not in its handlers. The thin is I would like to access the received messages within the (executable) program (basically the class with a main method) that created a new client object, using something like a timer which (or a loop) which would periodically check for new messages.
I would appreciate if someone could help me with this issue. Or at least tell me if its even possible with netty .
You're looking to translate netty's event-based model into a polling model. A simple way to do that is to create a message queue:
//import java.util.concurrent.BlockingQueue;
//import java.util.concurrent.LinkedBlockingQueue;
BlockingQueue queue = new LinkedBlockingQueue();
You need to make the queue available to your handler as a constructor argument, and when a message arrives you put it into the queue:
// Your netty handler:
queue.put(message);
On the client end, you can poll the queue for messages:
// The polling loop in your program:
message = queue.poll(5, TimeUnit.SECONDS);
The BlockingQueue offers you the choice between waiting for a message to arrive (take()), waiting a certain amount of time for a message to arrive (poll(long, TimeUnit)), or merely checking whether any message is available right now (poll()).
From a design perspective, this approach kills the non-blocking IO advantage netty is supposed to give you. You could have used a normal Socket connection for the same net result.