Sockets, BufferedReader.readline() - why the stream is not ready? - java

i'm learning java and i faced some problems with sockets. I developed a simple client-server app - kind of knock-knock, it performs 4 steps:
client sends some message to server
server recieves them and saves to file
server sends back to client some other messages
client recieves them and also saves to file
Problem appears on step #4: client doesn't recieve messages and never gets out the loop:
while ((inStr = in.readLine()) != null) {
writer.println(inStr);
}
where in is type of BufferedReader:
try {
socket = new Socket(ipAddress, 4444);
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
On server side messages are sent:
try {
socket = srvSocket.accept();
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
...
out.println("test from server #1");
out.println("test from server #2");
on client side i watched in.ready() - it returns false. On server side i watch out.checkError() - it returns true;
What am i doing wrong - why is the stream empty ?
Any help ia appreciated! :)

You are using public PrintWriter(OutputStream out, boolean autoFlush) which will flush automatically on new line or println. It does not autoflush after every write. You have to flush after every write.
Here is javadoc for the autoFlush param of the constructor:
A boolean; if true, the println, printf, or format methods will flush the output buffer

This might/might not solve your problem. But try keeping everything within Try Catch block. For eg: your ServerSocket initialization, writer blocks etc. If some error occurs, you might not be able to use writer anyhow, so there is no point in initializing it.
You might try writing to standard output stream for debugging instead of a file. Below code for Server/ Client is a minor variant of yours and its working.
Server:
Socket socket;
ServerSocket srvSocket;
BufferedReader in;
PrintWriter out;
try {
srvSocket=new ServerSocket(4444);
socket = srvSocket.accept();
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out.println("test from server #1");
out.println("test from server #2");
} catch (IOException e) {
e.printStackTrace();
}
Client
Socket socket;
BufferedReader in;
PrintWriter out;
String inStr;
try {
socket = new Socket("127.0.0.1", 4444);
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while ((inStr = in.readLine()) != null) {
System.out.println(inStr);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

Related

Java Socket: Server won't read input until client server is closed -> Server can't response to client

I'm trying to make a basic client <-> server connection in Java. When trying to write to the server, the client sends the details correctly, and the server stalls on reading it until the client output stream is closed. Though, once the output stream is closed it apparently closes the socket, and due to that the server can't reply to the client. Here's the main snippet of code that handles this interaction.
Client:
private void sendCmd(String cmd) {
String infoToSend = cmd;
try {
socket = new Socket(hostname, port);
System.out.println("Trying to send: " + com.sun.org.apache.xml.internal.security.utils.Base64.encode(infoToSend.getBytes()));
out = new DataOutputStream(socket.getOutputStream());
out.writeBytes(com.sun.org.apache.xml.internal.security.utils.Base64.encode(infoToSend.getBytes()));
out.flush();
System.out.println("Socket is flushed");
System.out.println("Waiting for Data");
InputStream is = socket.getInputStream();
System.out.println("Trying to get data");
BufferedReader input = new BufferedReader(
new InputStreamReader(is)
);
String line;
while((line = input.readLine()) != null) {
System.out.println(line);
}
socket.close();
} catch (IOException e) { e.printStackTrace(); }
}
Server:
public void run() {
System.out.println("Got Connection");
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new DataOutputStream(socket.getOutputStream());
String response;
System.out.println("Response:");
String decode = "";
while ((response = in.readLine()) != null) {
try {
decode = new String(Base64.decode(response));
} catch (Base64DecodingException e) {
e.printStackTrace();
}
}
System.out.println("Decoded: " + decode);
out.writeBytes("We got your message!");
out.flush();
out.close();
} catch (IOException e) { System.out.println("Fail"); e.printStackTrace(); }
Would anyone be able to guide me on how to fix this error. Sorry if it's super easy and I'm just unable to see it.
Sending
socket.shutdownOutput();
solved the issue.

Server doesn't receive message in client-server application

In my client-server application, the client sends message to Server and the Server should display the message. But in my case, the client is only able to send but the server can't achieve it.
I have tried with different port numbers (i.e. 8080, 8000, 4444 etc). It seems that the socket can set up the connection, but I really don't know why the server can't read the input from client.
This is my complete project (I have ignored the main classes for both application here, because I have nothing more than just calling the methods):
EchoServer.java:
package client.server;
import java.io.*;
import java.net.*;
public class EchoServer {
public EchoServer() {
}
public void establish() {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(8080);
} catch (IOException e) {
System.out.println("Could not listen on port: 1234");
System.exit(-1);
}
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.out.println("Accept failed: 1234");
System.exit(-1);
}
PrintWriter out = null;
BufferedReader in = null;
try {
out = new PrintWriter(
clientSocket.getOutputStream(), true);
in = new BufferedReader(
new InputStreamReader(
clientSocket.getInputStream()));
} catch (IOException ioe) {
System.out.println("Failed in creating streams");
System.exit(-1);
}
String inputLine, outputLine;
try {
while ((inputLine = in.readLine()) != null) {
out.println(inputLine);
if (inputLine.equals("Bye.")) {
break;
}
}
} catch (IOException ioe) {
System.out.println("Failed in reading, writing");
System.exit(-1);
}
try {
clientSocket.close();
serverSocket.close();
} catch (IOException e) {
System.out.println("Could not close");
System.exit(-1);
}
}
}
EchoClient.java:
package server.client;
import java.io.*;
import java.net.*;
public class EchoClient {
public EchoClient() {
}
public void establish() {
Socket echoSocket = null;
PrintWriter out = null;
BufferedReader in = null;
try {
//echoSocket = new Socket(InetAddress.getLocalHost(), 1234);
echoSocket = new Socket(InetAddress.getLocalHost(), 8080);
out = new PrintWriter(echoSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(
echoSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host.");
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O");
System.exit(1);
}
BufferedReader stdIn = new BufferedReader(
new InputStreamReader(System.in));
String userInput;
try {
while ((userInput = stdIn.readLine()) != null) {
out.println(userInput);
if (userInput.equals("Bye.")) {
break;
}
System.out.println("echo: " + in.readLine());
}
out.close();
in.close();
stdIn.close();
echoSocket.close();
} catch (IOException ioe) {
System.out.println("Failed");
System.exit(
-1);
}
}
}
Your server doesn't write the incoming text to the console but only back to the client which doesn't handle incoming text from the server yet.
(out isn't System.out but Socket.out!)
In your server you are listening with readLine() in whileloop
while ((inputLine = in.readLine()) != null) {
System.out.println("inputLine "+inputLine);
which is nothing but the inputstream from client. The above SOP will print the message from client. Try to flush your streams because it won't print until your buffer is full.
Code seems to be fine. If you write some thing on PrintWriter at both server & client ends, you will get output.
Add below code in server: ( After creating Socket with accept() API)
out.println("Hello from Server");
Add below code in client ( After creating Socket)
out.println("Hello from client");
Other suggestions:
1) Create a thread once you accept a Socket Connection at server and that thread should handle all IO processing
2) You can create thread at client end too after creating Socket with Server. The new thread should handle all IO processing

Read continuously?

I'm working on senior project and I'm trying to use this code to read from TCP socket but it reads from the socket once a time,but I need a continuous readings
Any hints
Thanks in advance!
This is the code:
class ClientAsyncTask extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
String result = null;
try {
Socket socket = new Socket(params[0],
Integer.parseInt(params[1]));
InputStream is = socket.getInputStream();
PrintWriter out = new PrintWriter(socket.getOutputStream(),true);
out.println(params[2]);
BufferedReader br = new BufferedReader(
new InputStreamReader(is));
//Read data in the input buffer
result = br.readLine();
//Close the client socket
socket.close();
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
Maybe you can use a loop for forever cycle? before you close socket with method
socket.close()
Because in official documentation:
Java doc
Once a socket has been closed, it is not available for further networking use (i.e. can't be reconnected or rebound).

Java - making different classes print to client instead of System.out

I'm converting a working single player game to run across a network.
It's a simple game that runs on a terminal.. it's just text in / text out with the program.
It has a few classes, most of which print to System.out or System.err
but I want to send these messages to the client instead of printing them on the server system.
How can I do this, when the socket i/o is made in the main thread of one class?
Basically how do I access this from the other classes?
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(45444);
} catch (IOException e) {
System.err.println("Could not listen on port: 45444.");
System.exit(1);
}
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
String inputLine;
String outputLine;
You can use System.setOut() and System.setErr() to redirect STDOUT and STDERR to arbitrary output streams (in your case, a network I/O stream).

Java Echo Server

Hello guys I am trying to do an echo Server by java but it is nnot working .. .I don't know why .. but it seems like the server is waiting the client and the client is waiting the server ... so they can't deliver the infromation to each other ..
here is the code
for the Server
ServerSocket server = null;
try {
server = new ServerSocket(3333);
System.out.println("Listening on 3333");
} catch (IOException ex) {
System.out.println("Error can't connect to 3333");
System.exit(1);
}
Socket clientSocket = null;
try {
clientSocket = server.accept();
} catch (IOException ex) {
System.out.println("Accept fail");
System.exit(1);
}
PrintWriter out = null;
try {
out = new PrintWriter(clientSocket.getOutputStream());
} catch (IOException ex) {
Logger.getLogger(JavaApplication20.class.getName()).log(Level.SEVERE, null, ex);
}
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
} catch (IOException ex) {
Logger.getLogger(JavaApplication20.class.getName()).log(Level.SEVERE, null, ex);
}
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String inputLine, outputLine;
while(!(inputLine=br.readLine()).equals("bye"))
{
out.print("echo: " + inputLine);
}
out.close();
br.close();
clientSocket.close();
server.close();
System.out.println("Server Exited");
and here is the code for the client
Socket client = null;
try {
client = new Socket("localhost", 3333);
System.out.println("Connected on 3333");
} catch (UnknownHostException ex) {
System.out.println("Couldn't connect to the server");
System.exit(1);
} catch (IOException ex) {
Logger.getLogger(KnockKnockClient.class.getName()).log(Level.SEVERE, null, ex);
}
PrintWriter out = null;
BufferedReader in = null;
BufferedReader stdIn = null;
try {
out = new PrintWriter(client.getOutputStream(), true);
} catch (IOException ex) {
Logger.getLogger(KnockKnockClient.class.getName()).log(Level.SEVERE, null, ex);
}
try {
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
} catch (IOException ex) {
Logger.getLogger(KnockKnockClient.class.getName()).log(Level.SEVERE, null, ex);
}
stdIn = new BufferedReader(new InputStreamReader(System.in));
String fromServer, fromUser;
while((fromUser=stdIn.readLine())!=null)
{
System.out.println("From user: "+ fromUser);
out.print(fromUser);
fromServer=in.readLine();
System.out.println(fromServer);
}
out.close();
stdIn.close();
in.close();
client.close();
System.out.println("client Exited");
Any Help with that ??
You're sending some string from the client ("Hello" for example), and you're trying to read it with readLine() on the server (and vice versa). readLine() will only return once it finds an EOL character, or once the input stream is closed.
Since the client doesn't send any EOL char, the server waits indefinitely, and the client also because it waits for the answer from the server.
Send "Hello\n", and it will work better.
After out.print(fromUser); use out.flush() in your client and server. flush will make sure it will right to the socket.
while((fromUser=stdIn.readLine())!=null)
{
System.out.println("From user: "+ fromUser);
out.print(fromUser);
out.flush();
fromServer=in.readLine();
System.out.println(fromServer);
}
out.close();
stdIn.close();
in.close();
client.close();
Regarding flush, Extracted from java doc.
Flushes the stream. If the stream has saved any characters from the various write() methods in a buffer, write them immediately to their intended destination. Then, if that destination is another character or byte stream, flush it. Thus one flush() invocation will flush all the buffers in a chain of Writers and OutputStreams.
If the intended destination of this stream is an abstraction provided by the underlying operating system, for example a file, then flushing the stream guarantees only that bytes previously written to the stream are passed to the operating system for writing; it does not guarantee that they are actually written to a physical device such as a disk drive.

Categories

Resources