I am a little gun shy about asking questions as they have been voted down, but this was is driving me crazy. I can see from all of the Serial port event handler questions that this is a popular subject. After much effort, I got the following code working:
public void serialEvent(SerialPortEvent evt) {
if (evt.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
try {
rdata = (byte) comIn.read();
line_buffer[line_ptr++] = rdata;
data_available = true;
// System.out.print((byte)rdata);
if( rdata == '\n') {
line_available = true;
}
}
catch (Exception e) {
System.out.print("Failed to read data. (" + e.toString() );
}
}
}
I say that it is working because if I uncomment the print, I see the data that I am expecting. I have also set breakpoints on the lines that set the data_available and the line available flags and they occur.
I am trying to communicate with this code with the following:
// Code that requests data to be send back
// Code that inserts a delay for data to be received
while( comm.line_avaiable() == false ) { }
for(int j=0;j< comm.line_ptr; j++) {
System.out.print( (char)comm.line_buffer[j] );
}
This code is to wait for data_available and then print the line of data received. With the code as shown, the while loop never gets data_available. Not only that, the event handler does not get any events. No data is echoed (with comment removed) and a break point is never hit.
IF i comment out the while loop that waits for data_available (and add the delays for the data to be received since we are running without a handshake, the data is received just fine. The event handler does hit break points if set and can echo data.
How can polling the line_available flag break the event handler?
Related
I wish to create a continuous Enhanced For loop within a Java program to output a message from an automatic ping to a Text area, and then to stop when a condition is met (IP address is offline). I have IP addresses in a String array called 'ip'. Works fine with no loop but requires continuous iterations until no response is detected.
Tried using Boolean loop which I included with the code - however does not append text to the TextArea and gets caught in a continuous loop.
for (String ip : listOfhosts) {
boolean repeatLoop = true;
try {
InetAddress i = InetAddress.getByName(ip);
textArea.append("Sending Ping Request to " + ip + "\n");
//boolean run = true;
//while (run){
if (i.isReachable(100)) { // 1 second limit
textArea.append("Host is online \n");
} else {
textArea.append("\nHOST IS OFFLINE\n");
//System.exit(0); //If something is offline, system will close. For now.
try {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress("email#gmail.com"));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("email#hotmail.com"));
message.setSubject("Test Mail");
message.setText("Test Mail," + "\n Sent From sendMail.java application\n");
//textArea.append("OK - Online \n");
Transport.send(message);
textArea.append("Mail Sent to email#email.com \n host " + ip + " is offline \n");
return;
} catch (MessagingException e) {
throw new RuntimeException(e);
}
}
} catch (Exception e) {
textArea.append("Unknown HOST\n");
e.printStackTrace();
}while(repeatLoop);
Gets caught in continuous loop - crashing the program. Any help would be great!
This code will block you UI. You should run it in a separate thread, and also add some delay between checks.
A simpler solution would also be to use a Timer
For instance, to check every second:
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
// your code
}
}, 1000);
There're two simple ways to break out of an enhanced for-loop in Java. One is to throw an exception, although for normal flow control this is considered exceptionally poor use of exceptions.
The other is to use break; which will break you out of the most immediate for-loop. People aren't always fond of return mid-function or break mid-for loop (or continue for that matter) as they can act a bit like goto/jump statements and reduce the clarity of your code. On the other hand, this is exactly what break is intended for, so there's no argument about misuse of the instruction.
An alternative approach is to use a normal while loop and forgo the enhanced for-loop for a normal iterator. In this case, listOfHosts.iterator(), will allow you to calculate a combination of .hasNext() and isReachable(...) to decide whether to continue looping.
// suppose listOfhosts is a String Array
List<String> srcHostList = new ArrayList<String>();
srcHostList.addAll(Arrays.asList(listOfhosts));
List<String> offlineList = new ArrayList<String>();
while( srcHostList.size() > 0) {
offlineList.clear();
for(String ip: srcHostList) {
boolean isOnline = true;
try{
// TODO check online
}catch(Exception ex){
// TODO handle exception
isOnline = false;
}
if(!isOnline) offlineList.add(ip);
}
srcHostList.removeAll(offlineList);
}
I have built a Spring CLI app which communicates with a server in an async fashion. The server was given, I did not create it, basically my app is required to open a TCP socket and send a JSON through it, then it sends back a JSON. It is mandatory not to use CLI parameters, but instead in the callback of the request I want to show the user a set of options for which he needs to select by inserting the corresponding number on the CLI. Most probably I'm not doing right something, because after entering the command, I see spring> on the console (this is an expected behavior) and it will block the async callback unless I press something (nothing is printed to the CLI when I receive the callback unless I press a bunch of enters - this is unexpected). To read from the console so far I used JLine's command line, what I would like to achieve is that when I get the response from the server and the callback is served, the console is given to the thread on which the callback is running (I instantly print the contents of the callback to the console, and I'm able to read the input without any tricks).
Some code:
public void runReceiver(){
receiverThread = new Thread(() -> {
byte[] digit = null;
int nb;
Iterator<CommandListener> it;
CommandListener listener;
String message;
List<CommandListener> listenersToRemove = new ArrayList<>();
while (true) {
try {
nb = communicatorInput.readInt();
digit = new byte[nb];
communicatorInput.readFully(digit);
} catch (IOException e) {
e.printStackTrace();
}
it = listeners.iterator();
while (it.hasNext()){
listener = it.next();
if (digit != null && digit.length > 0) {
message = new String(digit);
// the message was not acknowledged
if(message.contains("NACK")){
try {
listener.onError(message);
if (listener.isDone()) {
listenersToRemove.add(listener);
}
} catch (Exception e){
e.printStackTrace();
}
} else try {
listener.onCompleted(message);
} catch (InvalidObjectException e){
Main.logger.debug(String.format("Response could not be parsed as %s", listener.getCommandType()));
} catch (Exception e){
e.printStackTrace();
}
if (listener.isDone()) {
listenersToRemove.add(listener);
}
}
}
listeners.removeAll(listenersToRemove);
}
}, "receiverThread");
receiverThread.setDaemon(true);
receiverThread.start();
Then a CLI command (it expects no input here):
#CliCommand(value="start", help = "Starts stuff")
public void start() throws IOException, InterruptedException {
// this method is passed to the thread with the listener
getAvailabilities().updateAvailabilities("all", "all", "all", someListener);
}
And the callback for that listener:
someListener = new CommandListener() {
private String source = "Start some listener";
#Override
public void onCompleted(String r) throws IOException {
System.out.println("Which would you like to start?");
getAvailabilities().printAvailableBrands();
String brandNumber = "";
while(Objects.equals(brandNumber, "")){
System.out.println("Please enter the number of the Brand: ");
//when the callback arrives here I still only see ">spring:" and I get nothing printed on the console
brandNumber = cr.readLine();
if(!isInputAllowed(brandNumber, getAvailabilities().AvailableBrands.size())){
brandNumber = "";
}
}
BrandName = getAvailabilities().AvailableBrands.get(Integer.parseInt(brandNumber) - 1);
//updating the availabilities narrows down the things I list to the console, so I send an update after every selection
getAvailabilities().updateAvailabilities("all", BrandName, "all", getInterfaceListener);
done = true;
}
This might slightly connect to the issue that sometimes while debugging the CLI in Idea, it gets whacky inputs, eg. when I insert start it says No such command as ar, and if I press enter again, it'll say (some of) the rest: No such command as stt.
The problem is here:
if (listener.isDone()) {
listenersToRemove.add(listener);
}
If you want your listeners to be executed asynchronously you should not check their completion right away on the same thread as it will most likely return false.
The issue you might be having is that your listeners schedule some task but have no time to finish it as you immediately remove them after the loop:
listeners.removeAll(listenersToRemove);
It is very hard to tell what your logic is but I guess in the next while iteration your list is empty.
First, I'm not a developer (and I've been coding only for 2 weeks), so feel free to tell me I'm completely misunderstanding the thing (also, I wrote all of this for myself, so I'm sure it's super not cool) :). I want to learn and get it right, so I'm keen to listen to suggestions or complete rewrites.
I want to connect to a socket in non-blocking mode (I'm the client, not the server). I'll mainly need to read from it, but sometimes I'll need to write to it, too. The procedure is as follows:
Connect to socket
Send some initial requests to login to the server
Read from the socket
Sometimes, write some stuff (subscribe to certain information, for example)
My solution is as follows (I'm writing it in Java, because I've read it's a fast and good programming language, but I'm happy to change if required... hopefully not needed though!):
public class SocketClient {
public static void main(String[] args) {
new Feed().init();
}
private boolean isSocketConnected() {
return socket != null && socket.isConnected();
}
public void init() {
try {
if (isSocketConnected()) {
// What here if I'm in non-blocking mode?
// Would be good to know if the "close API" request succeeded
// otherwise next time I won't be able to connect to their socket...
sendCloseRequestToApi();
socket.close();
}
run();
} catch (Exception e) {
if (isSocketConnected()) {
// Same question as above...
sendCloseRequestsToApi();
socket.close();
}
}
}
public void run() throws IOException {
System.out.println("Starting connection in blocking mode...");
SocketChannel channel = SocketChannel.open();
socket = channel.socket();
socket.setReceiveBufferSize(RECEIVE_BUFFER_SIZE);
socket.setSendBufferSize(SEND_BUFFER_SIZE);
channel.connect(new InetSocketAddress("127.0.0.1", 2121));
channel.finishConnect();
System.out.println("Finished connecting in blocking mode");
// Writes to the socket (user and password)
initialiseTheApi();
System.out.println("Sent API requests in blocking mode");
System.out.println("Now we should probably go non-blocking (I guess)");
channel.register(selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ);
selector = Selector.open();
channel.configureBlocking(false);
System.out.println("Selector created and switched to non-blocking mode...");
long timeWithoutData = 0;
boolean needsReconnection = false;
while (!needsReconnection) {
selector.select();
Iterator < SelectionKey > keys = selector.selectedKeys().iterator();
while (keys.hasNext()) {
SelectionKey key = keys.next();
keys.remove();
if (!key.isValid()) {
continue;
}
if (key.isWritable()) {
// Execute write...
// What if I need to know the result to the write operation?
}
if (key.isReadable()) {
int dataRead = readDataFromSocket(buffer);
buffer.flip();
if (buffer.remaining() > 0) {
// I process the data read here,
// but sometimes the data sent is
// "reconnect to API". So I need to close
// the connection and start again.
// How can I do that if I'm in non-blocking mode?
// I mean, I need to make sure when I send that request
// (for reconnection).
// I need to know that the request got to the server and
// was processed OK before moving on and
// reading/writing again...
}
if (dataRead > -1) {
timeWithoutData = 0;
} else {
if (timeWithoutData > 0) {
long diffInMillis = System.currentTimeMillis() - timeWithoutData;
if (diffInMillis > 2000) {
System.out.println("Timeout or something? I need to reconnect I think");
needsReconnection = true;
}
} else {
timeWithoutData = System.currentTimeMillis();
}
}
// Do I even need this? Already did it before, right?
key.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE);
}
}
}
if (needsReconnection) {
// We need full reconnection, go back up and reconnect
init();
}
}
}
I removed imports and other non-useful methods for convenience, and to keep the post short.
As you can see in my questions in the code (plus some added ones):
Reconnection: If I'm in non-blocking mode, how do I know that my request got sent successfully to the server
If I read from the socket and the message is "Reconnect to API", how can I make sure that happens before any other read / write?
Do I need to send the interestedOps over and over again?
I should only connect once to the socket. The fact that I'm non-blocking doesn't change that, right?
I've seen this could all be simplified using Netty or something, but I'm already bloated with so much stuff! :(
I hope my questions are clear. Let me know otherwise, please.
Thanks a lot.
I was trying to do something that just didn't make sense. In my case I can definitely use a blocking connection, which I just didn't know about :/. Internet is a bad source of information sometimes! I kept reading over here not to use a blocking connection :D. But now it makes perfect sense the different scenarios. – Will
i've a memory leak problem on java Socket Object communication.
this is my send thread.
// create a new thread to send the packet
#Override
public synchronized void run() {
if(!genericSocket.isConnected()){
if(logger.isEnabled())
logger.logMessage(PFLogging.LEVEL_WARN, "Socket is close");
return;
}
int retry = 0;
boolean packetSent = false;
synchronized (objWriter) {
while ((retry < RETRY) && (!packetSent) && (genericSocket.isConnected())) {
try {
objWriter.writeObject(bean);
objWriter.flush();
// Try until the cache is reset and the memory is free
/*
boolean resetDone = false;
while(!resetDone) {
try {
objWriter.reset();
resetDone = true;
} catch (IOException r) {
Thread.sleep(1);
}
}
*/
// No error and packet sent
continuousError = 0;
packetSent = true;
} catch (Exception e) {
continuousError++;
if(logger.isEnabled())
logger.logMessage(PFLogging.LEVEL_ERROR, "Continuous Error [" + continuousError + "] sending message [" + e.getMessage() + "," + e.getCause() + "]");
// control the number of continuous errors
if(continuousError >= CONTINUOUS_ERROR) {
if(logger.isEnabled())
logger.logMessage(PFLogging.LEVEL_WARN, "I close the socket");
genericSocket.disconnect();
}
// next time is the time!
retry++;
}
}
}
}
the cache, when i sent about i packet per ms grow and grow!
if i add the commented part the cache is clean but when i need to send an async long message (about 3000 char) i see that the other message are lost!
There's another way to clean the cache without reset it??
ObjectOutputStream.reset() is not avoidable as it is the only means of clearing local hash tables, you can refer java source code for ObjectOutputStream for details of what happens in reset(), or else you will get OutOfMemoryError eventually
But you can very well implement a function like
private void writeObject(Object obj, ObjectOutputStream oos) throws IOException
{
synchronized(oos)
{
oos.writeObject(obj);
oos.flush();
oos.reset();
}
}
However you must ensure that all writes to ObjectOutputStream happens through this method.
the only solution i find is, first of starting a sending thread, to check if the thread pool is empty and in that case i reset the output stream.
I run the software all this night to check this.
Thanks all!
Matteo
I would use ObjectOutputStream.reset() periodically to clear the object cache for the stream.
You could even use it after sending every object. ;)
ciao :),
after ObjectOutputStream.flush() you can saftely use ObjectOutputStream.reset()
unless you are using the objWriter somwhere in another thread without using the synchronized (objWriter) statement.
In this case the best way IMHO is to use the objWriter in a thread, it will send object from a syncornized queue (see Queue sub-class http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Queue.html, for example http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ConcurrentLinkedQueue.html) that is filled from the other thread (remeber to use object.clone(), because the objcet itself isn't syncornized it can be modified by other thread while you are writing it or is in queue! if you clone it your clone will be a safe copy).
That way you don't need synchronized statment because data-flow between thread and ObjectOutputStream is already synchronized, and you will be less error-prone
I've been searching for four hours and this is driving me nuts. I'm going to try keeping this short, if you need more information/code ask and I'll edit.
So I have an Android client that connects to a server using PrintWriter and BufferedReader. The way it works is it starts a new ASyncTask() to load the connection. When the connection is made, it sends a "Join" message to the server, and then loads a listen thread that has a while loop waiting for UserInput.readLine() != null, and once broken it returns a string that runs a process function that takes the string and does it's action, and reloads the listen task.
//Listener thread
class listen extends AsyncTask<Integer, Integer, Void> {
#Override
protected Void doInBackground(Integer... params) {
//Disconnect variable that's only turned true on backpress
if (!disconnect) {
try {
message = Connection.listen(); //socket object
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPostExecute(Void result) {
// async task finished
if (!disconnect) {
say("INCOMMING"); //easy-made function for Toast
input(message);
}
}
}
and in that Connection:
public String listen() throws IOException {
String userInput;
while ((userInput = in.readLine()) != null) {
}
return userInput;
}
Now in my server java app, I have a thread that loads up other connection threads into an ArrayList and acts as a headquarters to dispatch messages to all child clients
In my connection:
while ((inputLine = in.readLine()) != null) {
//Tells HQ to process string, with id being who it's coming from
hq.Process(id, inputLine);
if (!connected)
break;
}
in HQ object:
public void Process(int id, String str) {
String[] msg = str.split(","); //split message
String send = " "; //string I print to console
if (msg[0].equals("join")) {
send = msg[1] + " has joined!";
parent.seats[cnew.get(id).seat] = id;
cnew.get(id).sendData();
System.out.println(id);
}
And after join, the HQ tells that connection to send that player's information to the phone
public void sendData() {
out.println("chips," + chips); // Update chip count
//give player his cards
out.println("card," + hq.parent.gameCards.getCard(10) + ","
+ hq.parent.gameCards.getCard(11));
//a cry for help to get some output on the phone
out.println("error,SAY THIS");
// out.flush(); //commented out because it didn't help at all
System.out.println("sending id " + id); //debug checker (ignore this)
}
My problem is, it worked when I connected four phones and they all sent toasts to each other.
But as soon as I changed it to send back data as soon as the player joins, I'm not getting a response in Android at all.
I can't figure out why it's not working. On server side, it's going through everything (Checked with system.prints). The connection IS made, and when I click buttons on the phone the Server is outputting it's responses. But the phone is not receiving anything -- I still don't know if the server is failing to send or the phone is failing to read. Can you see anything in the code that may be causing this? Need to see more? Or have any tips on how to debug the connection status? The listen() task is never finishing it's execution anymore.
UPDATE: So I figured out it's probably to do with my while() loop on android side, doh, probably never breaking. Stupid mistake. But I tried to add this as a tester, and still nothing:
public String listen() throws IOException {
String userInput;
while ((userInput = in.readLine()) != null) {
if (userInput.length() > 2)
break;
}
return userInput;
}
UPDATE: Next desperate update -
When I hit "back" (which sends quit msg to server that closes connection, and calls out.close and the rest.close) then I get a never ending loop of "MSG" Toast's -- The Toast that I put when an input is recognized. Is a out.close causing a block?
So it turns out, println on the server's side wasn't printing a new line -- adding + "\n" at the end of the server's messages made it go through. Why? I don't know..