Reputation: 67
I can't figure out why. When the server sends a string to the client, the client gets it just fine. But when I added code to my Client class to send a string to my Server, it doesn't work. Help?
edit: So I deleted the out.close(); in my Server class and replaced it with skt.shutdownOutput(); but now when I call my classes I get:
======================
Server has connected!
Server: Sending message: Test string to show connection between server and client.
Client: Received message: null
Server: Received message: null
Why?
Client Class:
import java.lang.*;
import java.io.*;
import java.net.*;
class Client {
public static void main(String args[]) {
}
//for receiving messages from Server
public void receiveMessage() {
try {
Socket skt = new Socket(InetAddress.getLocalHost().getHostName(), 1234);
BufferedReader in = new BufferedReader(new InputStreamReader(skt.getInputStream()));
//while (!in.ready()) {}
System.out.println("Client: Received message: " + in.readLine()); // Read one line and output it
in.close();
//skt.close(); //maybe delete
} catch (Exception e) {
System.out.print("Client had error receiving message.\n");
}
}
//for sending messages to Server
public void sendMessage(String message) throws IOException {
try {
Socket skt = new Socket(InetAddress.getLocalHost().getHostName(), 1234);
PrintWriter pw = new PrintWriter(skt.getOutputStream());
System.out.println("Client: Sending message: " + message);
pw.print(message);
//skt.close(); //maybe delete
} catch (Exception e) {
System.out.println(e);
System.out.print("Client had error sending message.\n");
}
}
}
Server Class:
import java.lang.*;
import java.io.*;
import java.net.*;
import java.util.concurrent.*;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Server {
String message = "Test string to show connection between server and client.";
public void Open() {
final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(10);
Runnable serverTask = new Runnable() {
@Override
public void run() {
try {
System.out.println("Opening...");
ServerSocket srvr = new ServerSocket(1234);
while (true) {
Socket skt = srvr.accept();
clientProcessingPool.submit(new ClientTask(skt));
}
} catch (Exception e) {
System.out.println(e);
System.out.print("You're opening too many servers in the same location, fool!\n");
}
}
};
Thread serverThread = new Thread(serverTask);
serverThread.start();
}
private class ClientTask implements Runnable {
private final Socket skt;
private ClientTask(Socket skt) {
this.skt = skt;
}
@Override
public void run() {
//for sending messages
System.out.println("======================");
System.out.println("Server has connected!");
PrintWriter out = null;
try {
out = new PrintWriter(skt.getOutputStream(), true);
} catch (IOException ex) {
System.out.println(ex);
System.out.println("Server had error sending message.");
}
System.out.print("Server: Sending message: " + message + "\n");
out.print(message);
//out.close();
try {
skt.shutdownOutput();
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
/*
try {
skt.close();
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}*/
//for receiving messages
//maybe make message procesing method
try {
BufferedReader br = new BufferedReader(new InputStreamReader(skt.getInputStream()));
System.out.println("Server: Received message: " + br.readLine()); // Read one line and output it
//br.close();
//skt.close(); //maybe delete
} catch (Exception e) {
System.out.println("Server had error receiving message.");
System.out.println("Error: " + e);
}
}
}
}
Thank you for any advice.
Upvotes: 0
Views: 14183
Reputation: 34618
out.print(message);
out.close();
By closing your PrintStream
you are closing the underlying OutputStream
.
The documentation of getOutputStream()
in Socket
says:
Closing the returned
OutputStream
will close the associated socket.
So when you close your PrintStream
, you also close the socket. Close your streams only when you are done with all communications between client and server for the current session.
The next problem you have (after your edit) is that you are not flushing the data. Your client connect, the server prints, without flushing, therefore the data is still waiting in the buffer, not in the stream. Closing a stream as you did previously would also flush the data, but now that you are just throwing the stream away, the data that was not flushed is discarded.
Hence, the stream closes, and the client sees the null
that indicates the end-of-stream.
So you need to flush the data before you discard the stream.
And the server is reporting that it has received null
because nothing is sent to it on its input stream. The client receives the information and then exits, which causes the socket to close, the streams to close, and the server to see an end-of-stream.
If you call your sendMessage
method, you'll see pretty much the same. The stream is writing something but nobody is listening for it. Because the message is short, the server doesn't block writing it, but nobody is reading it on the other side and it has the potential to block. Then, the server tries to read what was sent to it. But your client doesn't flush the data before it completes execution and closes the socket. Thus, the server will also see null
.
Upvotes: 3