I'm trying to make a connection between a server and multiple clients, but it doesn't work even for one. All I want to do is to send from the client an object using the ObjectOutputStream class. The connection is made successfully at the beginning but when I try to send the object to the server it fails.
This is the client part which is written in the main method of a class:
Socket socket;
OutputStream out;
ObjectOutputStream fout;
boolean connected=false;
if (!connected) {
try {
socket = new Socket("localhost", 8000);
out = socket.getOutputStream();
fout = new ObjectOutputStream(out);
fout.flush();
connected = true;
fout.writeObject(ac1);//ac is an object of Plane class
} catch (Exception ex) {
System.out.println(ex.toString());
}
}
This is the server:
public class server {
static class ServerThread implements Runnable {
Socket client = null;
public ServerThread(Socket c) {
this.client = c;
}
public void run() {
try {
System.out.println("Connected to client : "+client.getInetAddress().getHostName());
Plane ac=null;
InputStream in=client.getInputStream();
ObjectInputStream fin=new ObjectInputStream(in);
while(client.isConnected()){
ac = (Plane)fin.readObject();
System.out.println(ac.toString());
}
client.close();
} catch (Exception e) {
// System.err.println(e.getMessage());
e.printStackTrace();
}
}
}
public static void main(String args[]) {
try {
ServerSocket server = new ServerSocket(8000);
while (true) {
Socket p = server.accept();
new Thread(new ServerThread(p)).start();
}
} catch (Exception ex) {
System.err.println("Error : " + ex.getMessage());
}
}
}
Could anyone tell me what is the problem?
Your client never closes the socket, and presumably exits, so the connection is reset. So close the socket.
NB isConnected() is not a valid loop condition. It will never become false. Your loop should terminate when EOFExceprion is caught.
Related
I have a problem with my application. If I run server and clients on the same computer it works fine. No errors. But if I run server on one PC and I try to connect form other computers I get "timeout exception" or If I manage to connect I will get errors while sending data.
Server code (not all):
// server loop - listening for connections
public void runServer()
{
try {
ServerSocket serverSocket = new ServerSocket(port, 10);
System.out.println("Server up.");
while (true)
{
System.out.println("waiting for new connection...");
Socket socket = serverSocket.accept();
System.out.println("Someone connected");
Thread t = new Thread (new ServerThread(socket));
t.start();
System.out.println("new thread");
}
} catch (IOException ex) {
Logger.getLogger(KsiegarniaServer.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("Server error");
}
// this is thread that is opened when new client connects
private class ServerThread implements Runnable
{
Socket socket;
ObjectInputStream in;
ObjectOutputStream out;
String playerLogin;
int playerID;
public ServerThread(Socket s) {
this.socket = s;
}
public void run() {
try {
Msg m;
in = new ObjectInputStream(socket.getInputStream());
out = new ObjectOutputStream(socket.getOutputStream());
System.out.println("Streams are ready!");
while ( (m = (Msg) in.readObject()).getHeader() != 0 )
{
respondToClient(m); // switch with cases that are running depending on message header
}
} catch (IOException ex) {
//Logger.getLogger(SpaceBattleGameServer.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("IOException - public void run()");
} catch (ClassNotFoundException e) {
System.out.println("ClassNotFoundException - public void run()");
} finally {
// other stuff
}
I'm kind of stuck on one issue. I got a client-server app in Java, where multiple clients can connect to a server. Now I have a cyclic operation, which is getting the current time (corresponding to my ClockTask on the server side). But I don't really know how do I transmit this time data to all connected clients. It should be done somehow by ObjectOutputStream I guess, but it would be nice if someone could clue me in.
Here's my server code, together with thread running a client connection:
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
boolean listeningSocket = true;
try {
serverSocket = new ServerSocket(11111);
} catch (IOException e) {
System.err.println("Could not listen on port: 11111");
}
while(listeningSocket){
System.out.println("Waiting for a client to connect...");
Socket clientSocket = serverSocket.accept();
System.out.println("Client connected!");
ConnectThread ct = new ConnectThread(clientSocket);
ct.start();
}
serverSocket.close();
}
}
Connect thread:
public class ConnectThread extends Thread{
private Socket socket = null;
public ConnectThread(Socket socket) {
super("ConnectThread");
this.socket = socket;
}
#Override
public void run(){
ObjectOutputStream serverOutputStream = null;
ObjectInputStream serverInputStream = null;
try {
System.out.println("check");
serverOutputStream = new ObjectOutputStream(socket.getOutputStream());
System.out.println("check");
serverInputStream = new ObjectInputStream(socket.getInputStream());
serverOutputStream.writeInt(42);
System.out.println("check");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
try {
serverOutputStream.close();
serverInputStream.close();
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
and the client:
public class Client {
public static void main(String[] arg) {
Socket socketConnection = null;
ObjectOutputStream clientOutputStream = null;
ObjectInputStream clientInputStream = null;
try {
socketConnection = new Socket("127.0.0.1", 11111);
clientOutputStream = new ObjectOutputStream(
socketConnection.getOutputStream());
clientInputStream = new ObjectInputStream(
socketConnection.getInputStream());
System.out.println("check");
System.out.println(clientInputStream.readInt()); // HERE'S WHERE THE EXCEPTION OCCURS
} catch (Exception e) {
System.out.println("The following exception has occured and was caught:");
System.out.println(e);
}
finally{
try {
clientOutputStream.close();
clientInputStream.close();
socketConnection.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Clock task:
public class ClockTask extends TimerTask {
#Override
public void run() {
DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
Calendar c = Calendar.getInstance();
System.out.println(dateFormat.format(c.getTime()));
//some object output stream here??
}
}
I don't suggest sending a Calendar object as it is a very expensive object using around 2900 bytes. Instead you could send a long value over a DataOutputStream which would use 8 bytes.
Note: you would need to correct for the latency between the client and the server otherwise the time will be always delayed.
A simple way to address this is for the client to send a message to the server with a timestamp as long, the server responds with it's own time stamp and you can assume that the delay is half the round trip time. You can then apply an EWMA (Exponentially Weighted Moving Average) to get a reason average of the difference in the clock on the server and the client.
I got to stage where client and server communicate, sending messages from and to each other.
The problem I am having is how to close the connection without causing an error?
If I terminate one of the apps (either server or client) that causes the connection to be lost, and then it causes the loop that is waiting for input to loop indefinitely and showing null's.
I tried closing sockets, buffers and even the thread, didn't work.
This is the client side
public void onClick(View view) {
try {
EditText et = (EditText) findViewById(R.id.EditText01);
String str = et.getText().toString();
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())), true);
out.println(str);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
class ClientThread implements Runnable {
#Override
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVERPORT);
CommunicationThread commThread = new CommunicationThread(socket);
new Thread(commThread).start();
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
This is the server side
class ServerThread implements Runnable {
public void run() {
Socket socket = null;
try {
serverSocket = new ServerSocket(SERVERPORT);
} catch (IOException e) {
e.printStackTrace();
}
while (!Thread.currentThread().isInterrupted()) {
try {
socket = serverSocket.accept();
CommunicationThread commThread = new CommunicationThread(
socket);
new Thread(commThread).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Both use these classes:
class CommunicationThread implements Runnable {
private Socket clientSocket;
private BufferedReader input;
public CommunicationThread(Socket clientSocket) {
this.clientSocket = clientSocket;
try {
this.input = new BufferedReader(new InputStreamReader(
this.clientSocket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
String read = input.readLine();
updateConversationHandler.post(new updateUIThread(read));
//***HERE EXTRA BIT FOR THE SERVER
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class updateUIThread implements Runnable {
private String msg;
public updateUIThread(String str) {
this.msg = str;
}
#Override
public void run() {
text.setText(msg);
}
}
the only difference is the server has this bit where it says above ***HERE EXTRA BIT FOR THE SERVER
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())), true);
out.println("Message recieved");
so basically, client connects, server accepts, then client sends message, servers receives message and shows it, and then sends "Message received" to the client, and the client shows it.
All this works fine, but once the connection is lost, they hang on showing null repeatedly, and I have to force the app to close.
You aren't checking for end of stream. If readLine() returns null, the peer has closed the connection, and you must do likewise and stop reading.
It's hard to believe you really need a new thread for every line to update the UI.
I'm trying to create a live messenger application. But the code hangs when trying to readObject from an ObjectInputStream with no reason. No exception is thrown.
try {
System.out.println("Trying to connect to server");
socket = new Socket(InetAddress.getByName("localhost"),6789);
System.out.println("Connected to server");
inputStream = new ObjectInputStream(socket.getInputStream());
outputStream = new ObjectOutputStream(socket.getOutputStream());
outputStream.flush();
System.out.println("Streams are set up.");
window.toggleTyping(true);
System.out.println("Typing is now enabled");
String inputMsg = null;
do {
try {
System.out.println("Reading object");
inputMsg = (String)inputStream.readObject();
System.out.println("Object read");
} catch(ClassNotFoundException ee) {
System.out.println("Clas not found exception");
ee.printStackTrace();
}
} while(!inputMsg.equalsIgnoreCase("/exit"));
closeConnection();
}catch(IOException ex) {
ex.printStackTrace();
}
The last message that is printed is "Reading object".
try {
serverSocket = new ServerSocket(6789);
System.out.println("Socket created. About to accept connections");
Socket s = serverSocket.accept();
new Thread(new Chat(s)).start();
} catch(IOException e) {
e.printStackTrace();
}
And the class Chat:
public class Chat implements Runnable {
private Socket socket;
private ObjectOutputStream outputStream;
private ObjectInputStream inputStream;
public Chat(Socket s) {
System.out.println("Chat class constructor called");
this.socket = s;
try {
outputStream = new ObjectOutputStream(socket.getOutputStream());
outputStream.flush();
inputStream = new ObjectInputStream(socket.getInputStream());
System.out.println("Chat streams are now set up");
}catch(IOException ex) {
ex.printStackTrace();
}
}
private void closeChat() {
try {
outputStream.close();
inputStream.close();
socket.close();
System.out.println("Chat is now closed");
}catch(IOException ex) {
ex.printStackTrace();
}
}
#Override
public void run() {
System.out.println("Chat class method run called");
try {
outputStream.writeObject("Connection is cool");
outputStream.flush();
System.out.println("Text sent");
String inputMsg = "";
do {
try {
inputMsg = (String)inputStream.readObject();
System.out.println("Message read:"+inputMsg);
}catch(ClassNotFoundException e) {
e.printStackTrace();
}
}
while(!inputMsg.equalsIgnoreCase("/exit"));
closeChat();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
The reason every chat is a different thread is that I'm planning to implement multiple one on one chats someday.
This is because the reading method is a blocking method. This means it is trying to read until it gets a -1 to show that the read data are finished. Ensure that the OutputStream which writes to this socket is sending this. So you invoke at sending socket the ObjectOutputStream.flush(); method after you wrote the data or just close the output stream after writing. Closing this one would'nt be reasonable, because probably you may want to send further data throug this stream later.
Just a general thing: You don't need to flush the outputstream immediatley after you have created it
I'm trying to make a simple ECHO server that can manage more client.
Server Class:
public class EchoServer {
protected int port ;
protected ServerSocket socket;
private Socket acceptedSocket;
public EchoServer(int port) throws IOException {
this.port = port;
socket = new ServerSocket(port);
}
public void start() throws AcceptingClientException {
while(!socket.isClosed()) {
try {
acceptedSocket = socket.accept();
}
catch (IOException e){
throw new AcceptingClientException();
}
ClientHandler ch = new ClientHandler(acceptedSocket);
ch.run();
}
}
}
Runnable client handler:
public class ClientHandler implements Runnable {
Socket socket;
public ClientHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
PrintWriter From_Server = null;
BufferedReader To_Server = null;
String to_server_string = null;
try {
From_Server = new PrintWriter(socket.getOutputStream());
To_Server =
new BufferedReader(
new InputStreamReader( socket.getInputStream()));
System.out.println("Stream opened.\n");
while(true) {
if(To_Server.ready()){
System.out.println("Reading input line.\n");
to_server_string = To_Server.readLine();
if(to_server_string.equalsIgnoreCase("quit")) {
System.out.println("Connection closed on user request.\n");
From_Server.print("Bye :)\n");
From_Server.close();
To_Server.close();
socket.close();
}
else {
System.out.println(
"String '" +
to_server_string+"' is not 'quit', echoing.\n");
From_Server.print("ECHO: "+to_server_string+"\n");
System.out.println("String written on stream, flushing.\n");
From_Server.flush();
}
}
}
}
catch (IOException e) {
System.out.println("Stream error (connection closed?).\n");
}
}
}
Main Class
public static void main(String[] args) {
try {
EchoServer server= new EchoServer(9999);
server.start();
}
catch (IOException ex) {
System.out.println("Unable to start server (port is busy?)\n");
Logger.getLogger(SimpleServer.class.getName()).log(Level.SEVERE, null, ex);
}
catch (AcceptingClientException e){
System.out.println("Unable to accept client\n");
}
}
More than one client is able to connect to the server, but the ECHO will works only with one client at the time (if I close the connection with one client the server will start to handle another one automatically), but I can't understand why: when a client connects to the server, the associated socked created with server.accept() is passed to a new instance of a runnable client handler which is started with handler.run() and the server should go back on waiting in server.accept() (unless the ServerSocket is closed).
I'm assuming the issue should be with this method of the server class:
public void start() throws AcceptingClientException {
while(!socket.isClosed()) {
try {
acceptedSocket=socket.accept();
}
catch (IOException e){
throw new AcceptingClientException();
}
ClientHandler ch = new ClientHandler(acceptedSocket);
ch.run();
}
}
But I can't figure out what is wrong with it...what am I missing?
Your code:
ClientHandler ch = new ClientHandler(acceptedSocket);
ch.run();
doesn't start a new thread, it delegates to ClientHandler.run() in the same thread.
To start a thread, use new Thread( ch ).start(); since ch is of class ClientHandler which implements Runnable.