This is the first time I am not able to find the problem/bug in my code so now I am asking stackoverflow xD
I am currently learning how to write a simple Server - Client network to understand how Sockets and Server Sockets in Java work. Therefore, I wrote a "program" consisting of a Server, Client and Handler class. The Handler class is responsible for receiving the Client's messages and sending a response. Sending from Server to Client works perfectly fine, the Client receives the message. However, when the Client sends a message to the Server, it does not receive anything. The BufferedReader I am using is stuck on the readLine() request.
//This is the broken down version of what is happening in my Handler class
ServerSocket server = new ServerSocket(port); //These two lines of code actually happen in the Server class
Socket client = server.accept(); //but to simplify it I put them here
//Setting up the IO
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
//The Handler is waiting for the Reader to be ready and then prints the input
//Additionally, it sends a confirmation to the client
while(true) {
String input;
if(in.ready()){
if ((input = in.readLine()) != null) {
System.out.println(input);
out.println("Message Received");
if(input=="close") break;
}
}
}
//Expected output: "Message Received"
//Actual ouput: none, it gets stuck at in.ready() or in.readLine()
When I send a message from the Client it should just print the message and send a confirmation to the client but instead it either never gets past the if(in.ready()){...} part or gets stuck at if((input=in.readLine())!=null){...} if I remove the first if-statement. I used IntelliJ to debug it and the InputStream doesn't contain any message or the carriage return which is expected by readLine(). I find that to be really weird as the sending and receiving part of both the Server as well as the Client class is (mostly) the same.
The only thing I could think of that would maybe be the cause of this problem is that the Client somehow has problems sending the message.
//This is the broken down version of what is happening in my Client class
Socket client = new Socket();
client.connect(new InetSocketAddress("localhost",port));
//Setting up the IO
Scanner scanner = new Scanner(System.in); //I am using a Scanner for the message inputs
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
String input;
System.out.println("Enter the first Message: ");
while ((input = scanner.nextLine()) != null) {
String inServer;
System.out.println(input); //The input is correct
out.println(input); //I am suspecting it has something to do with this line or the PrintWriter
//This part works perfectly fine here while it does not in the Handler class
if (in.ready()) {
if ((inServer = in.readLine()) != null) {
System.out.println(inServer);
}
}
System.out.println("Enter next Message: ");
}
Expected output: inServer
Actual output: inServer
As you can see, the general setup of this part is the same as in the Handler class, yet something seems to go wrong when sending to the Server. I don't know if it is the Server (I don't think so because the same code for receiving messages works just fine in the Client class) or the Client, where in that case it would have to be a problem with the PrintWriter or something like that.
I have already looked at other/ similar questions here on stackoverflow but didn't find anything that would solve my problem.
The full code for the classes if someone wants to replicate everything in detail: (Pastebin links)
Server class
Client class
Handler class
Well, it seems the question has been answered...
It seems like it had something to do with the IntelliJ project the code was in. I had to move it into a new project and now it works.
The issue is resolved now and if someone wants to use this code as a base for a Server-Client system, I'll leave the pastebin-links working.
My suggestion is that you use read() method of the classes that implement Reader (BufferedReader is one of them). The syntax would be like this :
String data = "";
int i;
while ((i = in.read()) != -1){
data += (char)i;
}
This way is a lot more reliable and does not have the carriage return problem.
Related
I've got a fairly simple multi-thread chat program, where a server receives data from multiple clients and is then supposed to relay the messages back to all clients.
While the server does receive all its data properly, I can't seem to make the clients receive the returned values.
I've read through plenty of code and suggestions from both StackOverflow and other forums, but I can't seem to find the issue.
The ServerThread has the PrintWriter "out", declared and grabbed as such:
private PrintWriter out;
public PrintWriter getWriter(){
return out;
}
public void run() {
try{
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader (new InputStreamReader(socket.getInputStream()));
This method in the ServerThread is supposed to pass the data along:
if(input != null){
//Loggs message to file:
loggMessage(input);
//Loggs message to Server GUI
setOutput(input);
//Prints message to Output
System.out.println(input);
//Sends message to other clients:
for(ServerThread c : UserList){
System.out.println("Client discovered");
PrintWriter clientwriter = c.getWriter();
clientwriter.write(input);
System.out.print(input + " <-- was written to client");
}
}
The console (and file) get all messages as expected, but the clients don't. This is, as far as I can tell, either caused by something being off with that line in this batch of code, or something being wrong clientside
Clientside:
in = new BufferedReader (new InputStreamReader(socket.getInputStream()));
The "in" is declared like that, a few rows before the following chunk of code:
if(in.ready()){
String serverin = in.readLine();
System.out.println(serverin);
setOutput(serverin);
}
This system.out.print doesn't print anything. This makes me believe that something is wrong already at the if, but I'm not sure what that would be.
So, the clients won't receive the messages, and I'm not sure why.
When the program is run, the server indicates that all clients have been found and messages appropriately, yet they won't receive anything.
Any ideas?
I think that this call to in.ready() is wrong.
if(in.ready()){
String serverin = in.readLine();
System.out.println(serverin);
setOutput(serverin);
}
There is no need to call ready() because in.readline() will wait(block) until there is input.
An other issue is that readline() will wait(block) until the server send a newline, and only return the string once it gets a newline so are you sure that input contains a newline?
So, after quite a lot of testing and comparing code, I've finally found the issue.
The "clientwriter.write(input)" should have been "clientwriter.println(input)". After changing that the whole system worked as intended.
This is my first time using a Socket client Server system. I'm running into an error with the server side of my system and I do not know where it is coming from.
My client is running fine and closing but my server this is the function for
public void run() throws Exception
{
ServerSocket SRVSCK = new ServerSocket(444);
Socket Sock = SRVSCK.accept();
String Message="";
InputStreamReader IR = new InputStreamReader(Sock.getInputStream());
BufferedReader BR = new BufferedReader(IR);
Message = BR.readLine();
while(Message!="exit"){
System.out.println(Message);
Message = BR.readLine();
}
SRVSCK.close();
Sock.close();
System.out.println("here");
}
But this is the error I'm getting. It doesn't get out the while loop. I've tried breaking out the loop early based on the value of Message but it doesn't. And I can't figure out why. I've checked the thread and nothing seems to be the same. If it matters the information from the client is coming from a file.
First of all, you should probably stick to Java naming conventions of starting with lowercase for variable names. Next, when comparing Strings, don't use :
string1 == string2
string1 != string2
Those won't work. Instead, use
string1.equals(string2)
Message!="exit" should not be used for string comparison. To compare String in java equals method is used. Use
!Message.equals("exit")
I am working on class project for a remote string processor. It's my very first project in Java, so I do not really understand what all is going on...
I have everything finally working from Client to Server, but when it comes for the server to send the results back to the client, they both stay hang up and won't do anything until I forcefully close the server. Then "voilĂ !"... everything I was waiting for shows up on the client side.
If you have encountered such an issue, you probably are smiling right now as you click in the Answer box down below :)
Here is part of the server-side functions code, they give an idea about what I'm expecting to see on client-side as output.
//Get an output stream for writing to the client socket dataSocket
PrintStream socketOutput = new PrintStream(dataSocket.getOutputStream());
// some code here then
// This is where the various functions are executed depending on
// the value of the code entered by the user.
// A string, an integer, or a
// Boolean value depending on the case will be returned and printed
if (string1 != null && string2 != null) {
System.out.println("STRINGS 1 AND 2 WERE NOT NULL, SO LET'S ENTER SWITCH");
switch (code) {
case 1:
System.out.println("IN CASE 1");
int returnedSign = string1.compareTo(string2);
if (returnedSign > 0) {
System.out.println("IN CASE 1, returnedSign > 0");
socketOutput.println(string1+" lexically follows "+string2);
}
else if (returnedSign < 0) {
System.out.println("IN CASE 1, returnedSign < 0");
socketOutput.println(string2+" lexically follows "+string1);
}
else if (returnedSign == 0) {
System.out.println("IN CASE 1, returnedSign == 0");
socketOutput.println(string1+" equals "+string2);
}
System.out.println("AT END OF CASE 1");
socketOutput.flush();// forcing the socketOutput to let go of any data
break;
Alright, and here is some client-side code that's supposed to receive the output of the server and display it on the client screen:
// Get an output stream for writing to the socket
ObjectOutputStream myOS = new ObjectOutputStream(clientSocket.getOutputStream());
// Get stuff from the server and display them on the client's screen
BufferedReader ois = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); ...
...// Write to the Stream, that is get the code and the two strings
// to the stream
String codeMadeString = Integer.toString(code);
String messageString = code+";"+string1+";"+string2;
System.out.println("User entered: "+messageString);
myOS.writeObject(messageString);
//String serverOut = "";
String serverOut = (String)ois.readLine();
serverOut+='\n';
serverOut+=(String)ois.readLine();
serverOut+='\n';
serverOut+=(String)ois.readLine();
serverOut+='\n';
serverOut+=(String)ois.readLine();
System.out.println("Server said she saw... \n "+serverOut);
myOS.flush();
// Close the data socket
clientSocket.close();
Again, my question can also be stated as "what should I do to make sure that what's sent by the server is seen by the client without me having to close force the server to close first?"
Notes: I am working from the Terminal on MacOS Mavericks.
Any constructive ideas are welcome. Also, I am not a specialist in this, so please...
UPDATE1: I added the declaration of socketOutput.
I was not closing the buffered reader at first. Then I closed it at the wrong place. And finally, I found out it needs to be just at the end of the infinite loop server-side.
So:
while(true){
// Some code;
// Get stuff from the server and display them on the client's screen
BufferedReader ois = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
// Some more code and then
ois.close(); // before I get outside the loop.
}
And that's it!
I have written a server is java here is the code:
public mainClass()
{
try
{
ss = new ServerSocket(8080);
while (true)
{
socket = ss.accept();
System.out.println("It is accept!");
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//out = new PrintWriter(socket.getOutputStream(),true);
line = in.readLine();
System.out.println("you input is :" + line);
//out.close();
in.close();
socket.close();
}
}
catch (IOException e)
{
}
and I am using an iPhone application as the client.
now what my problem is that the server is not reading the inputstream while the appication is running on the iphone.. But as soon as the application is terminated the java program prints out the String which has been sent to the server..Not sure what is happening here..sorry if this is not a good question..
- (void)viewDidLoad {
[super viewDidLoad];
socket = [[LXSocket alloc]init];
if ([socket connect:#"10.211.55.2" port:8080]) {
NSLog(#"socket has been created");
}
else {
NSLog(#"socket couldn't be created created");
}
#try {
[socket sendString:#"Hi This is a second test"];
}
#catch (NSException * e) {
NSLog(#"Unable to send data");
}
[super viewDidLoad];
}
thanks,
TC
From my own experience, readLine is not a good idea, especially when working with different languages and platforms, a better approach will be to use InputStreamReader and its read(char[] buff) method, and agree on both sides regarding the length to be sent each time.
Again, I have no reference to that, only my experience.
Also, looking at your code, you send a string without a new line character: [socket sendString:#"Hi This is a second test"]; maybe adding \n at the end will solve it for you.
My guess is that the client application doesn't send any line break at the end of the string it sends. So BufferedReader.readLine() waits for an EOL character, and only returns the string when the client application ends, because at this point the connection is closed and the reader knows there won't ever be an EOL, and the string is the last line it will ever receive.
BufferedReader can be dangerous; the buffering can cause short lines to get "stuck" if you're only reading a little data at a time, or if the data is coming across a network. If you're only using BufferedReader to get readLine(), then do this:
new BufferedReader(new InputStreamReader(socket.getInputStream()), 1);
That extra argument sets the buffer size to 1 character, effectively turning it off. That generally solves this kind of problem.
I have socket already declared socket like this:
serverAddr = InetAddress.getByName(this.ip);
socket = new Socket(serverAddr, port);
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
however, the following doesn't work. in.ready() always returns false and if removed the program will freeze at String message = in.readLine();
private void receive() {
try {
InputStreamReader isr = new InputStreamReader(socket.getInputStream());
System.out.println(isr.getEncoding());
BufferedReader in = new BufferedReader(isr);
if (in.ready()) {
String message = in.readLine();
if (message != null) {
if (listener != null) {
listener.receiveMessage(ip, message);
} else {
print("Client recieved: " + message);//
}
}
}
in.close();
} catch (Exception e) {
print("Error with input stream: " + e);
disconnect();
}
}
How could i solve this?
EDIT:
This is how sending looks like in my server class:
out.println(message);
out.flush();
This happens in a loop whenever i've put something in message. out is closed after this loop.
You shouldn't be using ready() like this. The javadoc says this:
"Returns: True if the next read() is guaranteed not to block for input, false otherwise. Note that returning false does not guarantee that the next read will block. "
Your code is implicitly assuming that ready() -> false means that the next read will block. In actual fact, it means the next read might or might not block.
As #EJP says ... just do the read call.
What could i do to prevent a block though? The client will be unable to send anything if it's blocked
If blocking in read is a problem for your application, either use a separate thread to do the reading, or change your code to use NIO channel selectors.
Just remove the in.ready() test. It isn't helping you. readLine() will block until there is data available. What else were you planning to do if no data has arrived yet?
There are 3 things that come to my mind:
You are re-opening the input stream in every receive call, and wrapping it into a BufferedReader. This might read more than a single line into the buffer, and after finishing (closing it), the remaining buffered bytes will no longer be available for subsequent receive calls
Did you think about using an own thread for reading the server messages? There it won't harm if it is blocked
I have experienced some problems when closing one side of a socket after writing data, and immediately closing it. Sometimes not all of the data was received by the other side, despite flush() and close() calls. Maybe this is also an issue in your situation
Edit:
Smiply keeping the in reference outside of the receive method will not fully solve your problem. You should use a while loop for reading all buffered messages and call the listener for everyone, e.g.:
if (in.ready()) {
String message;
while ((message = in.readLine()) != null) {
// ...
}
}
But watch out as the last line might be a partially read message (e.g. 3 and 1/2 messages were buffered). If this is an issue, you could read the messages char-by-char for determining when a line ends, and use a PushbackReader for putting back incomplete messages.
You may need to call out.flush() to flush anything in BufferedWriter