Server thread socket ignoring called method with readLine - java

I have a P2P network of nodes holding records of key:value, which can pass requests to other nodes on the network when the asked node doesn't hold the desired key. The operation always returns an "OK" or an "ERROR". However, when a server thread recieving the request passes it down to all the other connected nodes by calling a method, the anwser ("OK" or "ERROR") isn't captured by the method, but by the main loop in run().
Here is the simplified code:
the run() method of the server thread class:
public void run(){
String line;
try {
while (true){
line=in.readLine();
if(line!=null){
else{
switch (line.split(" ")[0]){
case "set-value":
out.println(setValue(line.split(" ")[1]));
break;
System.out.println("default:");
System.out.println(line);
break;
}
}
}
}
} catch (IOException e) {
System.out.println("connection closed with: "+socket.getInetAddress().getHostAddress()+":"+socket.getPort()+" (server socket)");
}
}
the setvalue() method:
private String setValue(String arg) throws IOException {
String setKey = arg.split(":")[0];
String setValue = arg.split(":")[1];
if(DatabaseNode.getKey().equals(setKey)){
DatabaseNode.setValue(setValue);
System.out.println("set-value successful, current record: "+DatabaseNode.getKey()+":"+DatabaseNode.getValue());
return "OK";
} else {
System.out.println("key not on this node, searching...");
for (ServerConnect sc : DatabaseNode.getConnectToClient()) {
System.out.println("sending set-value to: "+sc);
if(sc.sendRead("set-value "+arg ).equals("OK")) {
return "OK";
}
}
for (ServerThread st : DatabaseNode.getConnectedToServer()) {
if(st != this) {
System.out.println("sending set-value to: "+st);
if(st.sendRead("set-value "+arg).equals("OK")) {
return "OK";
}
}
}
}
return "ERROR";
}
and the problematic one, sendRead(), which is supposed to send a string and wait for the anwser, but instead is ignored and anwser is captured by the main run() method
public String sendRead(String str) throws IOException {
out.println(str);
String line;
System.out.println("sent "+str+" awaiting response...");
line = in.readLine();
System.out.println("got "+line);
return line;
}
Thank you for your help
I tried identifying the threads on incoming line, and I am absolutely sure that the same thread which is supposed to read from method just starts a new loop and does nothing with sendRead().
The socket is NOT static, autoFlush on BufferedReader is enabled.

I just figured out what was wrong, the readLine() call in run() steals the next line, leaving the method hanging.

Related

Android : Keep socket open to read message from server

I'm working on an Android application that
First, I have to connect to hardware server via TCP socket
After connected, I will have to send *99*1## to server, then server will response with "*#*1##*#*1##"
Then, I need to keep this socket alive and read incoming message
After this point, server can send me message from times to times. But, When will message sent or length of message are undetermined.
Every message will end with '##', For example, *1*1*18##, *1*0*19##, *1*1*#4*11## and else.
When client (this app) receive message, it will notify activity to update UI.
So, I create a thread subclass to do this
public class ServerThread extends Thread {
public interface OnReadListener {
public void onRead(ServerThread serverThread, String response);
}
Socket socket;
String address;
int port;
OnReadListener listener = null;
public ServerThread(String address, int port) {
this.address = address;
this.port = port;
}
#Override
public void run() {
try {
socket = new Socket(InetAddress.getByName(address), port);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
PrintWriter writer = new PrintWriter(bw, true);
writer.println("*99*1##");
writer.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while (!socket.isConnected() && !Thread.currentThread().isInterrupted()) {
line = br.readLine();
if (line != null) {
Log.i("Dev", "Line ")
if (listener != null) {
listener.onRead(this, line);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void setListener(OnReadListener listener) {
this.listener = listener;
}
}
And in the activity, I do it like this
public class MainActivity extends Activity {
ServerThread st = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
}
#Override
public void onResume() {
startMonitoring();
super.onResume();
}
#Override
public void onPause() {
stopMonitoring();
super.onPause();
}
private void startMonitoring() {
stopMonitoring();
st = new ServerThread(SERVER_IP_ADDRESS, SERVER_PORT);
st.setListener(new OnReadListener{
#Override
public void onRead(ServerThread serverThread, String response) {
runOnUiThread(new Runnable() {
#Override
public void run() {
// update UI or do something with response
}
})
}
});
st.start();
}
private void stopMonitoring() {
if (st != null) {
st.stop();
st = null;
}
}
}
After I start this activity, I found that
The message "*99*1##" has been send to server, I can see this message from server hardware.
But, I only got first line of response from server '*#*1##*#*1##'
After that, socket is still connected (stacktrace not printed) but I never got any further message from server. Listener never gets called.
I have no idea how to make this work. Any suggestion are welcome.
Some note you might need to know
I'm not quit sure that BufferReader is the right object I need for the job or not. Because when it failed to read, it will return null and the loop will keep running. I might need some object that can freeze the thread waiting for input. This object can wait for input as long as it takes since the server may send message in seconds, minutes, hours or more. Once message has received, the continue to execute the code and go to the next round of loop.
(I'm full-time iOS Dev, not really familiar with Java)
Final Edit
After I carefully check the code, I found the silly mistake I made
writer.println("*99*1##")
Basically, println will send "*99*1##" and then follow with newline. But my hardware server doesn't like that so it terminate the connection. That's why I got null from BufferReader's readLine().
After I change to
writer.print("*99*1##")
The server receive "*99*1##" and keep connection. Then, and I can loop to read response just like EJP suggest again
String line;
while ((line = br.readLine()) != null) {
if (listener != null) {
listener.onRead(this, line);
}
}
if (listener != null) {
listener.onTerminated(this);
}
while (!socket.isConnected() ...
The problem is here. The test is pointless anyway, as it will never be false, but negating it means that the controlled block will never execute. Just remove the isConnected() test.
when it failed to read, it will return null and the loop will keep running.
Because you didn't handle that case correctly. If line is null you must exit the loop and close the connection. The usual way to write that is:
String line;
while ((line = reader.readLine()) != null)
{
// ...
}
Your sleep in your loop is just literally a waste of time.
Try this
while (isRunning) {
line = br.readLine();
if (line != null) {
Log.i("Dev", "Line ")
if (listener != null) {
listener.onRead(this, line);
}
}
}
Note: isRunning is a boolean variable to control your thread life cycle. Whenever you want to stop this thread, set isRunning = false and call close() on your connection.
If you want to create a TCP server you should use ServerSocket instead Socket. Here is java document about socket but android use the same http://docs.oracle.com/javase/tutorial/networking/sockets/

Multi-threaded Java TCP Client

I am writing a Java client application(Basic Java Net package with TCP/IP). The client must take input from the system.in and at the same time must listen to any messages coming from server through socket inputstream.
Once an input from the system.in is received, the client will get that input, do some processing and send it to the server as a request.
So basically 2 processes run,
-listening to client request
-listning to server responses.
I implemented 2 threads for this and ran the processing of messages in the main thread.
Is this good enough design.?
And is there a way to return the message received from the system.in to the main thread. The threads run() method returns void. I used a volatile variable to return the string received but its said that volatile is very costly since it doesn't use cpu cache to store the variable.
You can review these two projects I've written for an example of java sockets and multithreading.
Client
Server
I guess the ClientExample is the one you are searcing for but you can take a look at the server part too.
Basically the idea is to start two separate threads that listen for the different inputs - socket and console.
final Thread outThread = new Thread() {
#Override
public void run() {
System.out.println("Started...");
PrintWriter out = null;
Scanner sysIn = new Scanner(System.in);
try {
out = new PrintWriter(socket.getOutputStream());
out.println(name);
out.flush();
while (sysIn.hasNext() && !isFinished.get()) {
String line = sysIn.nextLine();
if ("exit".equals(line)) {
synchronized (isFinished) {
isFinished.set(true);
}
}
out.println(line);
out.flush();
disconnect();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (out != null) {
out.close();
}
}
};
};
outThread.start();
and another thread for the socket input:
final Thread inThread = new Thread() {
#Override
public void run() {
// Use a Scanner to read from the remote server
Scanner in = null;
try {
in = new Scanner(socket.getInputStream());
String line = in.nextLine();
while (!isFinished.get()) {
System.out.println(line);
line = in.nextLine();
}
} catch (Exception e) {
// e.printStackTrace();
} finally {
if (in != null) {
in.close();
}
}
};
};
inThread.start();
I hope this will help you :)

SwingWorker: process() method is not being called

I have a SwingWorker thread which I'm using to update a UI JLabel, and aside from the the publish()/process() methods, the program works (in that the JLabel is successfully posted with the appropriate text/background/border etc.). However, I want to use a process() method to set the text of the JLabel to "Connecting..." while the doInBackground() does its work, but the process() method in my program is never called (I am obviously using the publish() method). Suggestions?
Here's the SwingWorker:
public class PcclientBackgroundWork extends SwingWorker < String, String> {
public JLabel connectionStatus2;
String msg;
/* Constructor */
public PcclientBackgroundWork(JLabel label){
connectionStatus2 = label;
}
/*Background work to determine Application connection status
and pass corresponding message (String msg) to done() */
#Override
public String doInBackground() throws Exception {
String serverName = "localhost"; //UDP is sent within same machine
int port = 6789;
try {
Socket client = new Socket(serverName, port);
BufferedReader in = new BufferedReader
(new InputStreamReader(client.getInputStream()));
while(!in.ready()){
publish("Connecting"); //Want this method called until the bufferedReader is ready.
} //Loops until ready
msg = in.readLine(); //Incoming text is only one line
if(msg.equals("Connection Unsuccessful"))
{
msg = "Application Connection Failed";
} else {
msg = "App Connected " + msg;
}
System.out.println("msg = " + msg);
in.close(); //Close reader
client.close(); //Close client socket
} catch (IOException e) {
e.printStackTrace();
msg = "Application Connection Failed"; //JLabel text set the same as
} //if connection is unsuccessful (lines 66-68)
return msg;
}
public void process(String msg){
System.out.println("process method called...");
connectionStatus2.setText(msg);
}
/*Method to set JLabel information when doInBackground() is complete */
#Override
public void done() {
try {
connectionStatus2.setText(get()); //get() is the return value of doInBackground (String msg)
connectionStatus2.setBorder(BorderFactory.createLineBorder(Color.black));
connectionStatus2.setVisible(true);
connectionStatus2.setOpaque(true);
if(get().equals("Application Connection Failed")){
connectionStatus2.setBackground(Color.PINK);
} else {
connectionStatus2.setBackground(Color.GREEN);
}
} catch (InterruptedException ex) {
} catch (ExecutionException ex) {
Logger.getLogger(PcclientUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
I did not post the UI thread because the SwingWorker functions to my liking aside from the publish/process methods. Thanks in advance!
The signature for process is process(List<V>), not process(V). Change your process method to process(List<String> list); you may get more than one item in the list, depending on how often publish was called before process has a chance to run.

calling methods from run() method in java multithreaded client-server architecutre

i am trying to call other methods in run() method. But only when i exit/terminate the client connection the methods are displaying the output.
For example: listall method should print when a client gives listall command. But it gets invoked only when client terminates the connection.
Can anyone please tell me what am i doing wrong here
public void run() {
try {
System.out.println("Client socket : "+ clientSocket);
clientPortNumber=clientSocket.getPort();
clients.add(clientSocket);
String line;
while(true) {
line=is.readLine();
//System.out.println(line);
if(line==null)
break;
String temp[]=line.split(" ");
if(temp[0].equals("ADD")) {
addRfc();//add method invocation
}
else if(temp[0].equals("LOOKUP"))
send(os);//send method invocation
else if(temp[0].equals("ListAll")) {
listAll(); /*listall method should print when cient gives listall command. But it gets invoked only when client terminates the connection*/
} else if(line.equalsIgnoreCase("quit")) {
break;
}
}
}
catch (IOException e) {
System.out.println(e);
}
}
Check the implementation of the client. It sounds like the client is buffered and you need to flush the request before the server receive the request.

Closing resources when thread is finished in Java

I have a thread that uses network port for communication. I added
cancel() method to stop the execution and close network resources (How to properly stop the Thread in Java?)
private class ServerThread extends Thread {
int portNumber;
String serverAddress = null;
public ServerThread(String serverAddress, int portNumber) {
super();
this.serverAddress = "localhost";
this.portNumber = portNumber;
}
#Override
public void run() {
ServerSocket listener;
Socket socket;
try {
listener = new ServerSocket(this.portNumber);
socket = listener.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(),
true);
while (!isInterrupted()) {
String input = in.readLine();
if (input != null) {
out.println(input);
System.out.println("Hi:" + input);
}
} // end of while loop
System.out.println("OUT"); <-- ???
socket.close(); <-- ???
listener.close(); <-- ???
} catch (IOException e) {
e.printStackTrace();
}
}
public void cancel() {
System.out.println("cancel called");
interrupt();
}
}
The issue is that when I execute the ServerThread, and send cancel() message to finish the execution, it seems like that the three lines of code never executed: System.out.println("OUT"); socket.close(); listener.close();.
It also seems like that I don't need to send cancel() message to finish the thread.
ServerThread s = new ServerThread(serverAddress, serverPortNumber);
s.start();
...
s.cancel(); // ???
What's the recommended way of closing resources used by threads?
Don't I have to close resources when thread is not used anymore? Or everything is just automatically processed?
ADDED
It seems like that the thread is killed automatically as this code just works.
while(true) {
String input = in.readLine();
if (input != null) {
System.out.println("Received:" + input);
out.println(input);
}
} // end of while loop
/* System.out.println("OUT");
socket.close();
listener.close(); */
Thread#interrupt() will not interrupt the blocking I/O call on the socket. Try setting a "stop" flag and closing the socket in the cancel() method instead, and deal with the exception and check the flag in the while loop.
InterruptibleChannels reacts on the interrupt call, but not "old fashioned" socket streams.
In Java 7 you can use the try (resource) {} catch idiom like this:
try (final BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
while ((line = reader.readLine()) != null) {
process(line);
}
} catch (IOException e) {
e.printStackTrace();
}
This will guarantee that the stream is closed properly once the try block is left. No matter what happens inside or how the try/catch terminates.

Categories