I'm making a console chat application and now I have some problems with displaying messages on the client program.
My client program has two threads a read thread and write thread. The read thread gets messages from the server and write sends messages. The write thread has a Console object reading one line with a some text indicating to the user where to write your message. It looks like this in the console:
[Username]: message goes here
And this works fine when you only want to send messages, but I also have a read thread which is receiving and displaying messages that it got from the server. Which messes up this whole input thing because for example when the read thread gets a message it just prints it to the console and then prints another indicator on the next line and then everything looks like this:
[Username]:
[qwerty]: hello
[Username]:
I tried deleting the first indicator by printing \b (backspace) escape character in a for loop that looks like this:
String username = "username";
String indicator = "[" + username + "]: ";
for (int i = 0; i < indicator.length(); i++)
{
System.out.print("\b");
}
It worked on regular text, but not on the indicator. I think that's because the Console object reading for input in the same line somehow gets in the way.
This problem is even worse when the user is typing out a message and in the middle of the typing the user gets a message this happens:
[Username]: Hel //the user wanted to type out hello but got cut off
[qwerty]: hello
[Username]:
If the user where to finish writing hello on the next line and then send it. For the other client the message would say hello with no sign that the clients writing was interrupted by him, but for the client writing the message it would look like it sent two separate messages. I don't know how to fix this at all. Any help is appreciated.
Code for write thread:
public static class write implements Runnable
{
public void run()
{
Console cons = System.console();
while (true)
{
username = "[dgsgsdfg]: ";
System.out.print(username);
String input = cons.readLine();
String msg = username + input;
System.out.println(msg);
}
}
}
Code for read thread:
public static class read implements Runnable
{
public void run()
{
try
{
while(true)
{
Thread.sleep(5000);
for (int i = 0; i < username.length(); i++)
{
System.out.print("\b");
}
System.out.println("\n[qwerty]: hello");
System.out.print("[dgsgsdfg]: ");
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
P.S: The code show here is from a different program I created to try and fix this problem and it only contains the text printing part, and no networking or server stuff. The writer thread every 5 seconds prints hello, to simulate receiving and displaying a message.
Related
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.
i'm trying to implement a telnet interface in a Processing sketch, to pass command and receive outputs on the console.
I'm learning those days about the VT100 set of commands, so i was finally able to understand how was possible to reprint on already printed strings by moving the cursor.
I saw that it is also possible for the program to get input from the console, like with the Get cursor position command.
myClient.write("\033]6n"); //^[6n
The problem is that just print on the client interface the position, while i would like to have it back on the host. Someone know if and how is this possible?
Thank you
Here some example code:
import processing.net.*;
Server myServer;
void setup() {
myServer = new Server(this, 10002); // Starts a myServer on port 10002
}
void draw() {
Client thisClient = myServer.available();
if (thisClient != null) {
if (thisClient.available() > 0) {
String recived = thisClient.readString();
println(recived);
thisClient.write("\033[2A\r\033[2K" + "You just wrote: " + recived + "\033[2K");
thisClient.write("\033[6n"); // this happear on the client side, i want it back somehow
}
}
}
void serverEvent(Server someServer, Client someClient) {
someClient.write("\nhello, type something please...\n");
}
I have implmented JSSC API so I can communicate with the Com Port.
I send a command like "N\r\n"
and what i receive in a normal hyperterminal should look like this:
0100071CA79215021803164442180000
0100071C9F5415021803164514520000
0100071CDF5115022106142956600000
NOK
But when i do the same with the JSSC API i receive this (only the first code)
010
0071CA79
2150218
0316444
218
The Problem is that i randomly receive bit parts and at the end of the code i lose some parts. But thats not important i only need the first 12 digits of every code.
The Question is now how do i get the function to only receive the full line and not bitparts?
This is the receiving part of the class
class PortReader2 implements SerialPortEventListener {
#Override
public void serialEvent(SerialPortEvent event) {
if(event.isRXCHAR()&& event.getEventValue() > 2) {
try {
// получение ответа от порта
String receivedData = serialPort.readString();
System.out.println(receivedData.length() + ":" + receivedData);
}
catch (SerialPortException ex) {
System.out.println("Error in receiving response from port: " + ex);
}
}
}
}
This is the sending part
public void sendCodeCommand(SerialPort serialPort) {
// writing string to port
try {
Thread.sleep(3000);
serialPort.writeBytes("N\r\n".getBytes());
} catch (SerialPortException | InterruptedException ex) {
Logger.getLogger(ComPortSendReceive.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("String wrote to port, waiting for response..");
}
To fix the stated problem you need to concatenate the strings you receive into another string that accumulates the string fragments you receive from the readString() function, which is in the serialEvent handler. Because it is it's owm thread it gets a certain amount of cpu time to get serial data so it effectively gets partial sequential reads of the serial port input data. So this example puts the partial inputs together to create the "whole" input.
String serialString;
So within the serialEvent handler:
try {
serialStringFragment = serialPort.readString();
serialString.concat(serialStringFragment);
}
Either the string you get from readString() or the accumulation string can be scanned for tokens like eol condition. For Example:
String [] dlLines = serialString.split("\r\n");
will break each line out to an element in the dlLines string array.
However I have found that if I have fixed length output from my target device this works better:
serialPort.readString(int bytecount);
inline with the write serial string, eliminating the serialEvent handler.
This is a bit contrived but In other words:
String expectedStringLength "0100071CA79215021803164442180000";
int serialstrlen = expectedStringLength.length();
So the serialstrlen should obviously become constants for each expected line.
serialPort.writeString("N\r\n");
serialPort.readString(serialstrlen+2); // assuming cr lf
should get you the first line.
Put the readString() in a loop, change serialstrelen argument value according to the expected strings. Check the strings for alternate content for error handling. This has worked for me.
I need a thread running in the background reading from a pipe but the loop suddenly stops & when I display the thread state I find it in TIMED_WAITING how to prevent it from such a behavior,below the code running within the thread, Thanks in advance.
BufferedReader in = null;
while (started) {
String xml = "";
// char [] buf=new char[250];
try {
in = new BufferedReader(new FileReader(pipeName));
while (!in.ready()) {
}
// in.read(buf,0,buf.length);
xml = in.readLine();
// in.close();
} catch (Exception e) {
System.out.println("error:" + e.getMessage());
continue;
}
if (xml != null && !xml.equals("")) {
System.out.println("recieved: " + xml);
}
}
Edit:
After using #thomas's link the program runs fine with the print but when I try to parse pr do some functions on the string the data read becomes un stable & incomplete
Sorry #thomas for the delay,
When I first asked the question I had two C programs and 1 java,
the first C program write in the pipe then unlinks it while the other one writes many times if it unlinks the pipe the thread in java stops after an interval of time, but if it doesn't unlink the data us recieved & printed well according to the edit assumed by #GregKopff but when I add xml parsing to the data written by the second program the data arrives corrupted & missing, I assumed that the xml parsing takes too much time, so I changed the format of the data sent by just adding a separator, I know it is not considered a solution but it worked for me, Sorry again for the delay If you want a version of the please ask, I hope it's helpful
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..