Java - TCP/IP - Server can't send message back to Client? - java

I want to send an object from my client to my localhost server to add to database, and send result back whether the object was sent successfully or not. The object was sent successfully, but my server doesn't send the result back to client, and causes my client frame form hanged due to waiting for response from server. I don't know what's wrong with my code. Can you tell me some ways to fix this?
Here is the function to send the result:
public void sendResult(String result) {
try {
Socket clientSocket = myServer.accept();
System.out.println("Connected to client");
ObjectOutputStream os = new ObjectOutputStream(clientSocket.getOutputStream());
os.writeObject(result);
System.out.println("Result sent");
} catch (Exception ex) {
ex.printStackTrace();
}
}
Where the send result function is called:
public void service() {
try {
if (receiveStudent() != null) {
Student std = receiveStudent();
if (dao.addStudent(std)) {
System.out.println("OK");
sendResult("OK");
} else {
System.out.println("FAILED");
sendResult("FAILED");
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
In addition, in the Service function, the console printed "OK", which means the if condition was satisfied.
receive student method:
public Student receiveStudent() {
Student s = new Student();
try {
Socket clientSocket = myServer.accept();
System.out.println("Connect to client successfully");
ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream());
Object o = ois.readObject();
if (o instanceof Student) {
s = (Student) o;
return s;
}
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}

Because of myServer.accept() in sendResult(), the server is again waiting for an incoming client connection while this already happened in receiveStudent(). Reuse that connection.
Share the client socket you've obtained in receiveStudent() by, e.g., turning it into a field.
public Student receiveStudent() {
...
try {
clientSocket = myServer.accept();
...
} catch (Exception ex) {
...
}
...
}
and then reuse that socket in sendResult() to send the result to the client.
public static void sendResult(String result) {
try {
...
ObjectOutputStream os = new ObjectOutputStream(clientSocket.getOutputStream());
...
} catch (Exception ex) {
...
}
}

If you want to send a String as object why don't you just use something like this:
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); //for sending String messages
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); //for getting String messages
... and then when you need to send you do it like this:
out.println(textToServer"); // send to server - don't forget LN in println.
out.flush(); // to clean buffer
It should do what you need to be done.
And make sure that your client class is waiting to get that InputStream you're sending, don't forget that, since maybe it's the problem in the Client side.
Maybe Client is not accepting that incoming Socket regardless if it's ObjectInputStream or BufferedReader that will accept the incoming socket object.
You could provide us a Client class so we can see if there's missing acceptance of incoming socket.
At the end of the method make sure you close your streams and sockets.
out.close();
in.close();
socket.close();
For more details check this, this and this. I hope I was helpful :)

You're calling accept() twice. This is meaningless. You need to:
Accept the connection. This returns a Socket.
Read the request and create the response.
Send the response, via the same Socket you accepted at (1).
You also want to create a new thread per accepted socket, and you also want to do all I/O in that thread, including creating the ObjectInputStream and ObjectOutputStream. Otherwise your server isn't properly multi-threaded and multi-client.

Related

Java ObjectInputStream(socket.getInputStream()) catches null object

I'm making a client server couple. My client connects to server very well and it creates ObjectInputStream(socket.getInputStream()) over the socket, from server to client and vice versa. Then for some mystical reason my ObjectInputStream of the server somehow catches a null object. Client haven't sent anything over the socket (I did put /../ over the object send method to make this sure and even System.out.printed all the objects sent earlier) Server catches that mystical object only once, and after that all the objects sent By client work just as they should..
class ClientThread extends Thread {
//The socket where to listen/talk
Socket socket;
ObjectInputStream sInput;
ObjectOutputStream sOutput;
InputStream fInput;
OutputStream Output;
//my unique id (easier for deconnection)
int id;
//Objects that we will be receiving
Incomingdata datain;
//the date we connect
String date;
Player player;
boolean Connected = false;
//Constructor
ClientThread(Socket socket){
id = uniqueId++;
this.socket = socket;
try{
sOutput = new ObjectOutputStream(socket.getOutputStream());
sInput = new ObjectInputStream(socket.getInputStream());
Output = socket.getOutputStream();
} catch (Exception e){
System.out.println("Couldn't create Input/Output streams");
}
date = new Date().toString();
}
// what will run forever
public void run() {
// to loop until LOGOUT
Connected = true;
while(Connected) {
try {
datain = (Incomingdata) sInput.readObject(); //<--- this catches the mystical null! Even if nothing is sent over the socket?
}
catch (IOException e) {
TextArea.AddLine("Exception reading Streams: " + e);
break;
}
catch(ClassNotFoundException e2) {
break;
}
You can only receive a null if you send a null.
(There is a widespread misconception that readObject() returns null at end of stream. It doesn't.)

readObject method only reads the first object it receives

Just to give the background of my issue; I'm writing a client server application. when a client initially connects, the server accesses the database and send all the items in a particular table to the client by writing the objects to an objectoutputstream in a for loop.
The issue is, the client reads only the first object that is being sent. Even if I create a new object and send it to the server for verification the client does not pick it up when the server sends it back after inserting to database... extract from code:
Server:
public void loadClients()
{
ArrayList <Client> list = dBCon.loadClients();
try
{
for (int i =0; i<list.size();i++)
{
sendtoClient(list.get(i));
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
public void sendtoClient(Object obj) throws IOException
{
_out.writeObject(obj);
_out.flush();
_out.reset();
}
Client:
socket = new Socket("localhost", 4447);
ois = new ObjectInputStream(socket.getInputStream());
oos = new ObjectOutputStream(socket.getOutputStream());
Object objIn = ois.readObject();
Client client = (Client)objIn;
switch(client.actionType)
{
case ("ADD"):
{
if(clientFrame.tbDeals!=null)
{
clientFrame.tbDeals.addClient(client);
break;
}
else
{
clientList.add(client);
System.out.println(client.clientName);
break;
}
}
}
Edit: I have tried with a while loop on the client side as well. then ois.available() returns 0....
You're reading exactly one object on the client side. That's all you're going to get.
available() is rarely if ever used when doing basic IO in Java, and generally isn't going to do what you think it does.
Reading from a ObjectInputStream is blocking, just like all other basic Java IO. Using readObject() you will either get an object, or an exception as noted in the javadoc
The most simplistic example of how you would handle this in a loop if you have no idea the number of objects you'll be receiving and expect the connection to stay open is:
while (true) {
try {
Object o = ois.readObject();
/// do something with the object you just read
} catch ( EOFException e) {
System.out.println("remote connection closed!");
e.printStackTrace();
break;
}
}

Getting Null String when reading from a socket

I am trying to write a client-server system using Sockets in java, however I cannot seem to read data sent from the server to the client.
Here is the code for the client:
public class ClientSocket
{
Socket clientSocket = null;
PrintWriter out = null;
BufferedReader in = null;
// establish a connection to All Care's server application through socket 4444 (adjust localhost to reflect the IP address that the server
// is being run from)
public ClientSocket()
{
try
{
clientSocket = new Socket("localhost", 4445);
out = new PrintWriter(clientSocket.getOutputStream());
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
}
catch (IOException e)
{
System.out.println("Could not connect to All Care Server Application");
}
}
public void closeClientSocket()
{
try
{
clientSocket.close();
}
catch (IOException e)
{
System.out.println("Could not close connection to All Care Server Application");
}
}
public String getMessageFromServer()
{
try
{
String input = in.readLine();
return input;
}
catch (IOException e)
{
System.out.println("Could not read message from server");
}
return "No Data";
}
public void sendMessageToServer(String message)
{
out.write(message);
}
}
And here is the Server code:
public class ArFileServer {
public static void main(String[] args)
{
ServerSocket serverSocket = null;
boolean listening = true;
try
{
serverSocket = new ServerSocket(4445);
// infinite loop to continually listen for connection requests made by clients
while (listening)
{
new ClientConnection(serverSocket.accept()).start();
if (serverSocket != null)
{
System.out.println("Connection to client established");
}
}
serverSocket.close();
}
catch (IOException e)
{
System.out.println("Error could not create socket connection to port");
}
}
}
public class ClientConnection extends Thread
{
private Socket socket = null;
public ClientConnection(Socket socket)
{
super("ClientConnection");
this.socket = socket;
}
// the thread that runs after a connection to the server has been accepted
#Override
public void run()
{
try
{
PrintWriter out = new PrintWriter(socket.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
sendMessagetoClient(out, "CONNECTION SUCCESS");
// check login credentials sent from client to the server
// if valid send back their encrypted password, otherwise output a login error message
// wait for user input and then do various processes based on their requests
in.close();
out.close();
socket.close();
}
catch (IOException e)
{
System.out.println("Client socket connection error");
}
}
// sends a message to the client
void sendMessagetoClient(PrintWriter out, String message)
{
out.write(message);
}
// listens for a message from the client
String getMessageFromClient(BufferedReader in)
{
try
{
String input = in.readLine();
return input;
}
catch (IOException e)
{
System.out.println("Could not read message from client");
}
return "No Data";
}
And here is the line of code im using to see if the data is being sent.
System.out.println(clientSocket.getMessageFromServer());
In your sendMessageToClient() method, you need to flush:
void sendMessagetoClient(PrintWriter out, String message)
{
out.write(message);
out.flush();
}
Or, when you create the PrintWriter, use the constructor with autoflush:
PrintWriter out = new PrintWriter(socket.getOutputStream(),true);
And when you write, instead of out.write(message) use printf() or println().
There are several problems here.
You are reading lines but you aren't writing lines.
You aren't checking the result of readLine() for null, which means the peer has closed the connection, which means you must do likewise.
You aren't flushing the PrintWriter after you write.
You are closing things in the wrong order. You must close the output writer/stream you have attached to the socket. Doing that flushes it and then closes the input stream/reader and the socket. Doing this in the wrong order loses the flush. Once you've closed the output you don't need the other two closes.
You are using PrintWriter, which swallows exceptions, across a network, where you need to know about exceptions and errors in communication, and you aren't checking for errors either. Use a BufferedWriter.
in the clint code you are not connecting with server socket.
for clint socket connection
socket soc= new socket ("server host ip",port);

Opening read/write streams multiple times from a Socket

In a class where I have ServerSocket listening for incoming connections, following is the code:
while(isRunning)
{
try
{
Socket s = mysocketserver.accept();
acknowledgeClient(s);
new ClientHandler(s).start(); //Start new thread to serve the client, and get back to accept new connections.
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
And following is acknowledgeClient(Socket s) code.
ObjectInputStream in = new ObjectInputStream(s.getInputStream);
ObjectOutputStream out = new ObjectOutputStream(s.getOutStream);
String msg = in.readObject().toString();
System.out.println(msg+" is Connected"); //Show who's connected
out.writeObject("success"); //Respond with success.
in.close();
out.close();
The run() method of the ClientHandler.
try
{
in = new ObjectInputStream(client.getInputStream());
out = new ObjectOutputstream(client.getOutputStream());
String msg = "";
while(!msg.equalsIgnoreCase("bye"))
{
msg = in.readObject().toString();
System.out.println("Client Says - "+msg);
out.writeObject("success");
}
in.close();
out.close();
}
catch(Exception ex)
{
ex.printStackTrace();
}
And following is the way how client program communicates with this Echo Server.
try
{
int count = 10;
client = new Socket("localhost",8666);
in = new ObjectInputStream(client.getInputStream());
out = new ObjectOutputstream(client.getOutputStream());
out.writeObject("Foo");
System.out.println("Connection Status : "+in.readObject().toString());
while(count>0)
{
out.writeObject("Hello!");
String resp = in.readObject().toString(); //Getting EOFException here.
System.out.println("Sent with :"+resp);
count--;
Thread.sleep(1000);
}
out.close();
in.close();
client.close();
}
catch(Exception ex)
{
ex.printStackTrace();
}
As you might have noticed that, after the client is acknowledged after connection, I close the read/write streams, and from new thread which is serving the client, I'm opening the stream again, and from the server reading/writing from the connected socket is started, but as soon as I attempt to read server's response on sending Hello! by client, it crashes with EOFException instead of getting success.
I know the causes for which EOF occurs but not getting the clue that why is it happening here, I'm not attempting to read socket that has nothing in its stream (it should have success as written by server).
Is it too early that client is attempting to read socket before server has printed Hello! on its end and written success as response?
P.S. : I know its not a good way to ask question by putting so much code, we're expected here to get answers of the issue and understand it rather than having our problem fixed by others and get away. So, I've provided this much code to show all aspects from the problem.
I studied the source code of ObjectInputStream, and it appears that the reference to the original input stream s.getInputStream() is stored inside the ObjectInputStream.
When you close the ObjectInputStream, s.getInputStream() is closed as well.
Once an input stream is closed, it cannot be opened again. Thus, you get an EOFException, which indicates that you are at the end of the stream (since the stream could not be opened again).
You should do something like this to acknowledge the client.
Inside the run() method of the ClientHandler:
try {
// acknowledge client
ObjectInputStream in = new ObjectInputStream(s.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(s.getOutStream());
String msg = in.readObject().toString();
System.out.println(msg+" is Connected"); //Show who's connected
out.writeObject("success"); //Respond with success.
// end acknowledge client
String msg = "";
while(!msg.equalsIgnoreCase("bye"))
{
msg = in.readObject().toString();
System.out.println("Client Says - "+msg);
out.writeObject("success");
}
in.close();
out.close();
}
catch(Exception ex)
{
ex.printStackTrace();
}
If you want to isolate the acknowledge code in a seperate method, just be sure to maintain a proper reference to the same ObjectInputStream without closing the stream, then pass the reference around.
I'm opening the stream again, and from the server reading/writing from the connected socket is started,
Once a stream is close, you can't open it again. In fact you can't use two Object stream on the same stream this way at all.
Instead you should create an object stream for input and output once and only once and not close it until you have finished.
Well take a look at this program, i wrote it to understand multiple clients and server communication, your question is answered in this program.
The Client side code
public class ClientWala {
public static void main(String[] args) throws Exception{
Boolean b = true;
Socket s = new Socket("127.0.0.1", 4444);
System.out.println("connected: "+s.isConnected());
OutputStream output = s.getOutputStream();
PrintWriter pw = new PrintWriter(output,true);
// to write data to server
while(b){
if (!b){
System.exit(0);
}
else {
pw.write(new Scanner(System.in).nextLine());
}
}
// to read data from server
InputStream input = s.getInputStream();
InputStreamReader isr = new InputStreamReader(input);
BufferedReader br = new BufferedReader(isr);
String data = null;
while ((data = br.readLine())!=null){
// Print it using sysout, or do whatever you want with the incoming data from server
}
}
}
Server Side code
public class ServerTest {
ServerSocket s;
public void go() {
try {
s = new ServerSocket(44457);
while (true) {
Socket incoming = s.accept();
Thread t = new Thread(new MyCon(incoming));
t.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
class MyCon implements Runnable {
Socket incoming;
public MyCon(Socket incoming) {
this.incoming = incoming;
}
#Override
public void run() {
try {
PrintWriter pw = new PrintWriter(incoming.getOutputStream(),
true);
InputStreamReader isr = new InputStreamReader(
incoming.getInputStream());
BufferedReader br = new BufferedReader(isr);
String inp = null;
boolean isDone = true;
System.out.println("TYPE : BYE");
System.out.println();
while (isDone && ((inp = br.readLine()) != null)) {
System.out.println(inp);
if (inp.trim().equals("BYE")) {
System.out
.println("THANKS FOR CONNECTING...Bye for now");
isDone = false;
s.close();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
try {
s.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new ServerTest().go();
}
}
Closing any input stream or output stream or reader or writer around a socket stream closes the socket, and by implication the other streams, readers, and writers.
Use the same streams, readers, writers for the life of the socket.

Duplicate reception of message when reconnecting a socket

I'm having problems with a simple java socket client: the connection is established properly and both server and client receive and send data. When the client loses connectivity for a couple of seconds, the socket is finished and reestablished. This is done ok but in that moment, the last received message by the client (previous to the reconnection) is received again (2 receptions of the same message) with no reason.
My code is:
To start the socket:
Socket sock = new Socket();
sock.bind(null);
InetSocketAddress isa = new InetSocketAddress(serverIPAddress,serverPort);
sock.connect(isa, conectionTimeOut);
sock.setKeepAlive(true);
InputStreamReader isR = new InputStreamReader(sock.getInputStream(), "UTF8");
reader = new BufferedReader(isR);
out = new BufferedWriter(new OutputStreamWriter(
sock.getOutputStream(), "UTF8"));
Reading data:
public class IncomingReader implements Runnable {
String message = "";
#Override
public void run() {
Thread thisThread = Thread.currentThread();
while (readerThread == thisThread) {
try {
while ((message = reader.readLine()) != null) {
manageServerMessage(message);
}
} catch (IOException e) {
Log.d(General.TAG, e.getMessage()+" "+e.getCause());
}
}
When the connection is lost:
public void stopSocket() {
readerThread = null;
try{
if (reader != null){
reader.close();
reader=null;
}
} catch (IOException e) {
Log.d(General.TAG, e.getMessage()+" "+e.getCause());
}
try{
if (out != null)
out.close();
} catch (IOException e) {
Log.d(General.TAG, e.getMessage()+" "+e.getCause());
}
try{
if (sock != null){
sock.close();
sock=null;
}
} catch (IOException e) {
Log.d(General.TAG, e.getMessage()+" "+e.getCause());
sock=null;
}
readerThread = null;
}
How are you re-establishing your Socket connection? I can see 2 possibilities at this stage...
You aren't fully removing all 'old' references before you recreate the connection. Are you creating a brand new Socket? BufferedReader? IncomingReader thread? etc. If there is something that you haven't recreated, it might be holding on to the previous value. If you're reusing your IncomingReader rather than creating a new one, it might still hold an old value.
If the connection is closed, how are you handling it on the Server side? If your Server is trying to send information to the Client, but the connection is broken, the Server may try to re-send the last message once the connection is re-established. Another possibility, if your Server doesn't close() the connection when it is broken, it too might be holding on to some old data.
Basically, as best as you can, you need to make sure that when the connection breaks, everything related to the connection on both the Client and the Server is completely closed and recreated using new Objects. If everything is a new Object, there's no possibility of any old data hanging around to confuse things.

Categories