I have a Java Client/Server chat application and after a connection gets established, only about 1 quarter of the data is being received by the recipient. What could the problem be? Here is a print screen of what happens exactly:
Code for reading from socket:
public void somethingElse(){
try {
if(in.readLine() != null){
messageBufferIn = in.readLine();
System.out.println(in.readLine());
chat.append(recipient + ": " + messageBufferIn + "\n");
}
} catch (IOException e) {
e.printStackTrace();
}
}
Code for thread that runs above method:
public class chatListener extends Thread{
static main main = new main();
//static Thread mainThread = new Thread(main);
public void run(){
while(main.isConnected == true){
main.somethingElse();
}
}
}
The above thread gets run as soon as a connection gets established
Thanks for any help
Each time you call in.readLine, the scanner moves down to the next line; you can't keep calling it a few times, as it will skip the lines you never used essentially. Try this to replace somethingElse():
public void somethingElse(){
try {
String line;//Added a variable to store the current line to; readLine is
//dynamic, it returns the next line each call, so if we store to a variable,
//we only call it once, and hold that value
if((line = in.readLine()) != null){// (line = in.readLine()) != null is shorthand to store readLine to line, and then check if that returned value is null or not
System.out.println(line);//Print out the line
chat.append(recipient + ": " + line + "\n");//Append it
}
} catch (IOException e) {
e.printStackTrace();
}
}
Before, you were calling in.readLine once to check if it was null, then you saved the next line, then printed the next one. Hence the pattern of (fail success fail | fail success fail etc.) = Only messages 2 + 5 showing up
Related
I am sending a some json to a php page from my java application which echos "finished" if successful. The json and php are working great. I am trying to pass a string to a thread and then change the value of the string to the echo from the php in the thread, and when the Thread is finished I want to use an if statement to determine if the URL connection was successfully completed... which it is I just can't get the value of the string from the Thread.
here is my code:
main.java
final String line = "unfinished";
Thread iURL = new instrURL(line, jsonArray);
iURL.start();
while(iURL.isAlive())
{
System.out.println("In wait loop");
}
System.out.println(line);
if(line.trim() == "finished")
{
System.out.println("Made it to finished");
}
else
{
System.out.println("Did not make it to finished");
}
instrURL.java
public class instrURL extends Thread{
String line;
String jsonArray;
public instrURL(String line, String jsonArray)
{
this.line = line;
this.jsonArray = jsonArray;
}
public void run()
{
try
{
URL url = new URL("http://fake.php?jsonArray="+URLEncoder.encode(jsonArray, "UTF-8"));
URLConnection conn = url.openConnection();
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
line = rd.readLine();
System.out.println(line);
rd.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
the console:
In wait while loop
In wait while loop
...
...
...
In wait while loop
finished
In wait while loop
In wait while loop
In wait while loop
unfinished
Did not make it to finished
As you can see from the console the Thread gets the finished, but once outside of the Thread the strings value is still unfinished.
Any help would be greatly appreciated.
You have at least four different String reference variables with the name line in your process, and updates to one won't be reflected in the other ones, which is why your program doesn't behave as expected:
final String line = "unfinished"; in main.java - looks like a
local variable on the stack
instrURL(String line, - a paramter to
the instrURL constructor
instrURL.line a member in the instrURL
class
String line; a local in the run() method in instrURL
All of these are distinct references, so assigning to one will not affect any of the others. Even beyond that, I don't see any assignments at all to any of the flavors of line in the instrURL class.
Generally speaking you should use established inter-thread communication methods such as Future, or shared statics under a lock, but probably the closest thing to what you want is to declare a static volatile String line somewhere, and refer to it in both main and your thread class, and remove all other copies of line.
Java compare string with equals method not with ==
if(null!line && line.trim().equals("finished"))
{
System.out.println("Made it to finished");
}
Inside run method you are not reading data from buffered reader and not changing the value of line, that's why you are getting same value as "unfinished", you need to read data like this
String currentLine
while ((currentLine = br.readLine()) != null) {
System.out.println(sCurrentLine);
}
after reading data from stream , set value in line string as
line="finished";
I send a message over sockets from an android app to a java program. This message is sent with a printwriter.
here is how I send my message from android to java program:
out.println("Hello there");
out.flush();
This is how I receive the message:
while(true){
String msg = in.readLine();
System.out.println("MSG: " + msg);
...some if-statements...
}
The output of the System.out.println is:
MSG: Hello there
*MSG: null*
How come I get null there? I'm only sending "hello there"..
Help would be appreciated, thanks!
EDIT: Actual code of the java program.
while (run) {
String msg = in.readLine();
String[] parts;
String username;
String password = null;
System.out.println("MSG: " + msg);
parts = msg.split("\\*");
username = parts[0];
password = parts[1];
boolean validUser = false;
validUser = db.authenticate(username, password);
if (validUser) {
db.updateIP(username, socket.getInetAddress().getHostAddress());
out.println("done");
out.flush();
} else {
out.println("loginfail");
out.flush();
closeSocketConnection();
}
}
}
private void closeSocketConnection() throws IOException {
in.close();
out.close();
socket.close();
run = false;
}
What is your exit condition for your while loop?
It looks to me like it is repeating and readLine will return null when the end of the stream has been reached causing MSG: null to be printed.
Updated given new information:
Assuming user*123 is a valid username/password combo then closeSocketConnection() is never called, the loop returns to the top, readLine returns null and you see your erroneous output. Followed by a NullPointerException on parts = msg.split("\\*");
Your loop should read:
while ((line = in.readLine()) != null)
{
// ...
}
At the moment you're processing the null that indicates end of stream inside the loop, hence you're printing it as a message when it isn't.
I'm making a simple chat server and just made it so each connection runs on a new thread.
The old version started a single thread for the server, it did a while loop, which would stop when a stop message was sent then close the socket.
The new version loops forever and create a new thread for each new connection. Now I cannot close the socket connection.
If you press a key and the main thread stops, the socket stays open. Thus when I run the program again I need to change the socket number.
code of server
while(true)
{
///////////////////////////////////////////////////
// get a new connection
///////////////////////////////////////////////////
System.out.println("Aceepting connections on port 1030 \r");
try{
// Get New Connection
// wait for ever on accepting new connections
server.setSoTimeout(0);
connection=server.accept();
cConnection thread = new cConnection("thread3", connection);
} catch(IOException ec)
{
System.out.println(ec.getMessage());
}
}
code that starts server
Now each message comes in on a new thread, so I cannot tell it to stop and close the socket.
You need to provide a flag that must be globally accesible, so when some client wants to stop the server then change the variable ans stops the bucle. By example:
class YourServer {
private static boolean execute = true;
public static synchronized void stop() {
execute = false;
}
public void yourMethod() {
while(execute) {
// implement your server here
}
}
}
When a client send the command STOP you must be do
YourServer.stop();
If you want a stop command to stop the server you can call System.exit() to force the program to store or just closing server is likely to be all you need.
Looking into your problem, I understood one thing, that since you are putting
while (true), so your control always gets stuck at connection=server.accept(); listening for a new connection. So in order to stop the sockets you need to first find a way to stop looping in that while loop. Either you can set a Variable, like (int clientsConnected) to check the number of Clients, when that comes to zero stop that while loop. So you can stop your sockets.
Below is my sample code for clients which is doing the same thing for closing the Sockets.
Hopefully this solves your problem.
class GetNamesFromServer implements Runnable
{
private Socket sForName, sForId;
private BufferedReader in, inForName, inForId;
private PrintWriter outForName, outForId;
private static String clientNames;
public GetNamesFromServer(Socket s1, Socket s2)
{
sForName = s1;
sForId = s2;
}
public void run()
{
try
{
outForName = new PrintWriter(sForName.getOutputStream(), true);
outForName.println(Client.clientName);
System.out.println("Send Name : " + Client.clientName);
outForName.flush();
}
catch(IOException e)
{
System.err.println("Error sending Name to the Server.");
}
try
{
inForId = new BufferedReader(new InputStreamReader(sForId.getInputStream()));
Client.clientId = (inForId.readLine()).trim();
System.out.println("Client ID is : " + Client.clientId);
}
catch(IOException e)
{
System.err.println("Error Receiving ID from Server.");
}
try
{
inForName = new BufferedReader(new InputStreamReader(sForName.getInputStream()));
while (true)
{
clientNames = inForName.readLine();
if (clientNames != null && clientNames != "")
{
clientNames = clientNames.substring(1, clientNames.length() - 1);
System.out.println("Names Received : " + clientNames);
String[] names = clientNames.split(", ");
Client.nameClients.clear();
for (String element: names)
Client.nameClients.add(element);
Client.nPane.setText("");
int size = Client.nameClients.size();
System.out.println("Size of list : " + size);
for (int i = 0; i < size; i++)
{
String name = Client.nameClients.get(i);
String colour = Character.toString(name.charAt(0));
name = name.substring(1, name.length()) + "\n";
appendToNamePane(name, ReceiveMessages.getColour(Integer.parseInt(colour)), "Lucida Console");
}
System.out.println("Clients Online : " + Client.nameClients);
}
int index = Client.nameClients.indexOf(Client.clientId + Client.clientName);
**if (index == -1)
{
sForName.close();
break;
}**
}
}
catch(IOException e)
{
System.err.println("Error Receiving Names of Clients from Server");
}
}
NEW EDITION :
You can add a cap to maximum number of clients that can connect, once that reaches your while loop will not go to connection = server.accept(); and hence when they are done chatting (after some time) i.e. totalClients = 0, you can stop your sockets as well, to stop the program.
if (totalClients == 0)
{
socket.close();
serverSocket.close();
}
Regards
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..
I am trying to run some shell scripts for Java by using commons exec package and clear the STDOUT & STDERR buffers by using PumpStreamHandler. Most of the scripts run fine without any problems but some of them hangs.
Particularly those scripts that takes some time to return. My guess is that the PumpStramHandle might be reading end of stream as there is nothing put on the stream for a while and after that the buffers fill up.
Is there any better way to get across this problem?
Extract the script/command being executed and run it yourself in a shell. When running things that are 'exec'd through some other language(c,c++, python java etc) and things start going 'wrong' this should be the first step.
You find all sorts of things going on. Scripts that stop and prompt for input(big source of hangups) errors that don't parse correctly, seg faults, files not found.
To expand on the first answer about running the commands directly to test, you can test your hypothesis with a simple script that sleeps for a while before returning output. If you
can't test your command, test your idea.
#!/bin/bash
sleep 60;
echo "if you are patient, here is your response"
Not the best solution. But does what I need. :)
class OSCommandLogger extends Thread {
private static final Logger logger = Logger.getLogger(OSCommandLogger.class);
private volatile boolean done = false;
private final String name;
// Each process is associated with an error and output stream
private final BufferedReader outputReader;
private final BufferedReader errorReader;
private final Logger log;
/**
* Reads the output & error streams of the processes and writes them to
* specified log
*
* #param p
* #param name
* #param log
*/
OSCommandLogger(Process p, String name, Logger log) {
// Create readers
outputReader = new BufferedReader(new InputStreamReader(p.getInputStream()));
errorReader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
this.log = log;
if (name != null)
this.name = name;
else
this.name = "OSCommandStreamsLogger";
}
private void logLine(BufferedReader reader, boolean isError) {
try {
String line = null;
while ((line = reader.readLine()) != null) {
if (log != null && log.isDebugEnabled()) {
if (!isError)
log.debug("[OuputStream] " + line);
else
log.warn("[ErrorStream] " + line);
} else
logger.debug(line);
}
} catch (Exception ex) {
if (log != null)
log.error(name + ":" + "Error while reading command process stream", ex);
}
}
public void run() {
while (!done) {
logLine(outputReader, false);
logLine(errorReader, true);
try {
// Sleep for a while before reading the next lines
Thread.sleep(100);
} catch (InterruptedException e) {
log.debug("Done with command");
}
}
// Process is done. Close all the streams
try {
logLine(outputReader, false);
outputReader.close();
logLine(errorReader, true);
errorReader.close();
if (log != null && log.isDebugEnabled())
log.debug(name + ": Closed output/ error Streams.");
} catch (IOException ie) {
if (log != null)
log.error(name + ":" + "Error while reading command process stream", ie);
}
}
public void stopLoggers() {
if (log != null && log.isDebugEnabled())
log.debug(name + ":Stop loggers");
this.done = true;
}
}
Usage:
Process p = Runtime.getRuntime().exec("Command");
OSCommandLogger logger = new OSCommandLogger(p, "Command", log);
// Start the thread using thread pool
threadExec.executeRunnable(logger);
int exitValue = p.waitFor(); // Wait till the process is finished
// Required to stop the logger threads
logger.stopLoggers();
logger.interrupt();