I am trying to test my chat client application by creating a socket and connecting it to the server, sending a message and closing the socket (via the server's close method). However, it seems that when I close the socket the client thread still awaits for client input. However, I have put if clause to stop it from waiting. Here is my test:
#Test
public void testMessagesReceived() throws IOException
{
ServerSocket s = server.getSocket();
System.out.println(s);
mysocket = new Socket("127.0.0.1", 3000);
final PrintWriter stream = new PrintWriter(mysocket.getOutputStream(), true);
stream.println("Default room");
}
#AfterSuite
public void stopServer() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
server.stop();
}
However, when the server.stop() executes and closes the socket I get an exception in the client thread which is alive and uses this socket, here:
public void acceptFromConsole() throws IOException {
if (!socket.isClosed()) {
final BufferedReader fromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String message;
while ((message = fromClient.readLine()) != null) { // Exception here
if (message.contains(TelnetUtilities.Quit.toString())) {
room.removeClient(id);
break;
}
}
Here is the full stacktrace:
java.net.SocketException: Socket closed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
at sun.nio.cs.StreamDecoder.read(Unknown Source)
at java.io.InputStreamReader.read(Unknown Source)
at java.io.BufferedReader.fill(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at com.egt.chat.server.ClientContainer.acceptFromConsole(ClientContainer.java:40)
at com.egt.chat.server.ClientContainerRunnable.run(ClientContainerRunnable.java:28)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
It seems to me that in one thread I close the socket ,however the client thread doesn't see the change on the socket and that check if(!socket.isClosed()) returns true and the flow of execution continues and while I try to read it of course throws exception that I am trying to read from a closed socket ,is there a way to overcome this?
Your code is working as it should be. When you forcefully disconnect the socket your code is the while loop:
while ((message = fromClient.readLine()) != null) { // Exception here
if (message.contains(TelnetUtilities.Quit.toString())) {
room.removeClient(id);
break;
}
readLine() is waiting for incoming data. If you would not close the connection it would wait forever for new data. Then you close the connection and readLine() (or better the underlaying socketRead method) now recognizes that it can't read data from a closed socket and raises the exception.
Therefore this exception is an expected exception at this point. Catch it and be happy.
I would do it this way: Add a boolean variable like stopServerCalled which is by default false and is set to true when stopServer() is called.
try {
while ((message = fromClient.readLine()) != null) { // Exception here
if (message.contains(TelnetUtilities.Quit.toString())) {
room.removeClient(id);
break;
}
} catch (SocketException e) {
// check if this is an expected exception and if yes ignore it
if (!stopServerCalled)
throw e;
}
Related
I understand why the binding error occurs, but I have followed any solution I can find and cannot get it to work.
Stack Trace
java.net.BindException: Address already in use: connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
at java.net.AbstractPlainSocketImpl.connect(Unknown Source)
at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.SocksSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.<init>(Unknown Source)
at java.net.Socket.<init>(Unknown Source)
at socket.ClientWorker.run(ClientWorker.java:30)
at java.lang.Thread.run(Unknown Source)
Picked up JAVA_TOOL_OPTIONS: -Djava.vendor="Sun Microsystems Inc"
Server Code
#Override
public void run() {
try {
ServerSocket listener = new ServerSocket(port);
while (running) {
Socket socket = listener.accept();
new Thread(new ServerWorker(socket, airport)).start();
}
listener.close();
} catch (IOException e) {e.printStackTrace();}
}
Each time the server gets an incoming connection, it creates a new thread to do the work.
Server Worker
#Override
public void run() {
try {
// Get message
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String number;
number = br.readLine();
// Add new arrival event
String[] splitMessage = number.split(" ");
String mode = splitMessage[2];
int time = Integer.valueOf(splitMessage[0]);
int airportID = Integer.valueOf(splitMessage[1]);
if(mode.equals("STANDARD")){
Event newEvent = new Event(EventType.ARRIVAL,time,airport);
airport.scheduleEvent(airportID,newEvent);
}
if(mode.equals("NULL")){
Event newEvent = new Event(EventType.NULL,time,airport);
airport.scheduleEvent(airportID,newEvent);
}
// Close
socket.close();
}
catch (IOException e){e.printStackTrace();}
}
Client
/*-- Send a message to a different airport --*/
public void sendMessage(int port, String message){
new Thread(new ClientWorker(port, message)).start();
}
The Client (airport object) calls this message when it want's to communicate with a different airport. A new thread is created to process the work.
Client Worker
#Override
public void run() {
try {
Socket s = new Socket("localhost", port);
OutputStream os = s.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
String sendMessage = message + "\n";
bw.write(sendMessage);
bw.flush();
s.close();
}
catch (UnknownHostException e){e.printStackTrace(); System.exit(0);}
catch (IOException e){e.printStackTrace(); System.exit(0);}
}
The error traces back to here - 'Socket s = new Socket("localhost", port);'
Notes
All work is done on the same machine.
Hundreds of messages could be sent each second.
All the clients are running in parallel.
The client may have to send multiple messages in (very) quick succession.
I thought I was making a new connection per message, but I must be misunderstanding something.
you are using Socket socket = listener.accept(); you need to close socket after use into server code.
`
You're probably exhausting the number of client connections you can concurrently establish; in that case abusing ServerSocket#setReuseAddress() probably isn't a good idea.
I thought I was making a new connection per message, but I must be misunderstanding something.
You are- that's the problem :) Consider some kind of connection-pooling to reuse existing connections rather than spinning up thousands at a time (if your client and server spans across hosts, even the overhead of establishing the connection could quickly become the bottleneck in a setup like this).
it is my first time using java networking. I have to use it for a project i am working on which is a simple card game. My server and client will communicate as the "Connection Received" does get printed. But after this line the following error occurs:
java.io.EOFException
at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at ClientConnectionManager.reciveData(ClientConnectionManager.java:49)
at LogicThread.getHandSize(GameLogic.java:22)
at LogicThread.run(GameLogic.java:16)
at java.lang.Thread.run(Unknown Source)
Exception in thread "Thread-4" java.lang.NullPointerException
at LogicThread.getHandSize(GameLogic.java:22)
at LogicThread.run(GameLogic.java:16)
at java.lang.Thread.run(Unknown Source)
the classes in question are:
static ObjectInputStream input;
static ObjectOutputStream output;
static Socket socket;
public static void connectToServer(){
try {
System.out.println("connecting");
socket = new Socket(ip, port);
input = new ObjectInputStream(socket.getInputStream());
output = new ObjectOutputStream(socket.getOutputStream());
output.flush();
System.out.println("connected");
reciveData();
logic.startLogic();
//listenForData();
} catch (IOException e) {
e.printStackTrace();
}
}
public static Object reciveData(){
try {
Object obj = input.readObject(); - Error is on this line
System.out.println(obj);
return obj;
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
return null;
}
The server code for sending data:
ServerSocket server;
server = new ServerSocket(2302);
Socket connection;
connection = server.accept();
output = new ObjectOutputStream(connection.getOutputStream());
public void sendData(Object data){
try {
output.writeObject(data);
output.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
I am not sure what causes this because the server sends a "Connection Received" which the client receives with no issue and prints. But any call from outside the connectToServer() Method cause the error above.
The peer has closed the connection. Somewhere the server is closing the accepted socket or one of its streams.
That implies that if the server has really called sendData() it must have thrown an exception you haven't mentioned.
I've tried making a simple server to accept multiple sockets & then let them input and receive an output.
But it seems like I am doing it wrong as I am getting many errors.
Is the way I am trying to do that bad? How can I do that in a better way?
I dont understand why do I get these errors:
Starting up..
Trying to listen...
Server is successfully running on port 43594
New connection: /127.0.0.1:60639
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
at sun.nio.cs.StreamDecoder.read(Unknown Source)
at java.io.InputStreamReader.read(Unknown Source)
at java.io.BufferedReader.fill(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at Client.getInputStream(Client.java:29)
at ClientHandler.run(ClientHandler.java:19)
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
at sun.nio.cs.StreamDecoder.read(Unknown Source)
at java.io.InputStreamReader.read(Unknown Source)
at java.io.BufferedReader.fill(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at Client.getInputStream(Client.java:29)
at ClientHandler.run(ClientHandler.java:19)
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
at sun.nio.cs.StreamDecoder.read(Unknown Source)
at java.io.InputStreamReader.read(Unknown Source)
at java.io.BufferedReader.fill(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at Client.getInputStream(Client.java:29)
at ClientHandler.run(ClientHandler.java:19)
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
at sun.nio.cs.StreamDecoder.read(Unknown Source)
at java.io.InputStreamReader.read(Unknown Source)
at java.io.BufferedReader.fill(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at Client.getInputStream(Client.java:29)
at ClientHandler.run(ClientHandler.java:19)
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
at sun.nio.cs.StreamDecoder.read(Unknown Source)
at java.io.InputStreamReader.read(Unknown Source)
at java.io.BufferedReader.fill(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at Client.getInputStream(Client.java:29)
at ClientHandler.run(ClientHandler.java:19)
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
at sun.nio.cs.StreamDecoder.read(Unknown Source)
at java.io.InputStreamReader.read(Unknown Source)
at java.io.BufferedReader.fill(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at Client.getInputStream(Client.java:29)
at ClientHandler.run(ClientHandler.java:19)
And many many more lines of errors. Its basically looping the same error over and over, but why?
I've commented the code so you can see what i've tried to do and maybe fix the way I do that.
public class Server {
private int port = 43594;
public void listen() {
System.out.println("Trying to listen...");
try {
final ServerSocket server = new ServerSocket(port);
// Create new thread to handle clients I/O
ClientHandler handler = new ClientHandler(server);
// START it
handler.start();
System.out.println("Server is successfully running on port " + port);
while (true) {
// New connection found create a new Client object
Client cl = new Client(server.accept());
cl.setup();
// add it to clietns list in the I/O handler
handler.clients.add(cl);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// start up
System.out.println("Starting up..");
// server instance
final Server server = new Server();
// create a new thread for server
new Thread(new Runnable() {
#Override
public void run() {
// listen for new connections
server.listen();
}
}).start();
}
}
public class ClientHandler extends Thread {
private Thread handler;
public ArrayList<Client> clients = new ArrayList<Client>(); // client list
private ServerSocket server;
public ClientHandler(ServerSocket s) {
server = s;
}
public void run() {
while(true) {
// Loop every time through every client and see if he has wrote
// anything to do server. I am 100% sure this is wrong, how can I do this
// without using multithreads (thread per client)?
for (Client c : this.clients) {
if (c.getInputStream() != null) {
// found input, return a message.
c.sendMessage("hey client");
}
}
try {
// sleep for 100ms
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Client {
private Socket socket;
private int clientId;
private BufferedReader inStream;
private PrintWriter outStream;
private boolean socketAlive = true;
public Client(Socket sock) {
this.socket = sock;
}
public void setup() {
setInputOutputStream();
System.out.println("New connection: " + this.getIpAddress());
this.sendMessage("Successfully connected!");
}
public String getInputStream() {
String toReturn = "";
try {
toReturn = this.inStream.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return toReturn;
}
private void setInputOutputStream() {
try {
inStream = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
outStream = new PrintWriter(this.socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendMessage(String s) {
this.outStream.println(s);
this.outStream.flush();
}
public String getIpAddress() {
return this.socket.getRemoteSocketAddress().toString();
}
}
And not sure if it will be useful, this is the client:
public class TestClient {
/**
* #param args
* #throws IOException
* #throws UnknownHostException
*/
public static void main(String[] args) {
try {
System.out.println("Client started");
Socket sock = new Socket("localhost", 43594);
Scanner scanner = new Scanner(System.in);
String input;
PrintWriter out = new PrintWriter(sock.getOutputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(sock.getInputStream()));
input = scanner.nextLine();
if (input != null) {
out.print(input);
}
if (reader.toString() != null) {
System.out.println(reader.toString());
}
} catch (IOException e) {
System.out.println("Client error");
}
}
}
Why is the connection keeps getting reset?
The client has no loop or delay, so it would just immediately quit as soon as it sent data. When a program quits, the operating system always closes all of its network connections!
Also, I don't think this does what you want it to do: System.out.println(reader.toString());. Check the output of the client!
You are writing things from the server that you aren't reading at the client. Instead the client just exits after the print. 'reader.toString() doesn't do any I/O. You need to call a read method.
If i start the Server first and then the Client everything works perfect, but when i start the client first and then the server(making sure that the Client is able to connect when the svr crashes and then goes online again) the Client does connect to the Server, but after 2,3 seconds it throws a SocketException: Connection reset. I don't know what is causing it and i would really apprechiate it if someone could help me figure this out.
Server code that handles the clients:
public ServerHandler(Socket socket){
try{
pw = new PrintWriter(socket.getOutputStream());
writerHolder[userCounter] = pw;
InputStreamReader in = new InputStreamReader(socket.getInputStream());
reader = new BufferedReader(in);
userCounter++;// Increment the number of people connected
}catch(Exception ex)
{
ex.printStackTrace();
}
}
Client code that connects to the Server:
private void startConnection()
{
try
{
sock = new Socket("192.168.1.5", 5000);
InputStreamReader input = new InputStreamReader(sock.getInputStream());
reader = new BufferedReader(input);
pw = new PrintWriter(sock.getOutputStream());
JOptionPane.showMessageDialog(null, "Connected to the server!");
}catch(IOException ex)
{
//timer.reconnectTimer(20);
ex.printStackTrace();
}
}
StackTrace:
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
at sun.nio.cs.StreamDecoder.read(Unknown Source)
at java.io.InputStreamReader.read(Unknown Source)
at java.io.BufferedReader.fill(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at homeControl.ServerHandler.run(ServerHandler.java:52)
at java.lang.Thread.run(Unknown Source)
"Connection reset" usually means that the remote side closed its side of the socket without reading the data that you sent. Make sure that you read data sent to you before you close a socket.
I want to implement a handler in my code to allow a client to automatically connect to a second instance of a server on the same network if the server connected to this client is not responding after 10 seconds. What am I doing wrong??
private static void connectToServer(String serverHostname, int port) throws UnknownHostException, IOException
{
try {
echoSocket = new Socket(serverHostname, 10118);
out = new PrintWriter(echoSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(echoSocket
.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Unknown host: " + serverHostname);
System.exit(1);
} catch (IOException e) {
System.err.println("Not connected to server: "
+ serverHostname);
System.exit(1);
}
}
public static void main(String[] args) throws IOException {
listServer.add("10.196.113.31");
listServer.add("10.196.113.27");
BufferedReader stdIn = new BufferedReader(new InputStreamReader(
System.in));
try {
if (args.length > 0)
serverHostname = args[0];
System.out.println("Trying to connect to host " + serverHostname
+ " at port 10118.");
connectToServer(getServer(), 10118);
echoSocket.setSoTimeout(10000);
String userInput;
System.out.print("Input: ");
while ((userInput = stdIn.readLine()) != null) {
out.println(userInput);
if (!echoSocket.isConnected()) connectToServer(serverHostname, 10118);
System.out.println("echo: " + in.readLine());
System.out.print("Input: ");
}
} catch (SocketTimeoutException e) {
NextServer();
connectToServer(getServer(), 10118);
System.out.println("Timeout");
// TODO: handle exception
}
out.close();
in.close();
stdIn.close();
echoSocket.close();
}
private static void NextServer(){
idServer ++;
}
private static String getServer(){
return listServer.get(idServer);
}
EDIT
When I run the server, then the client, everything is fine. Then I start the second server on another machine on the same network, and try to send text from the same client, the client should automatically detect that the first server is disconnected, connect to the second instance of the server and send the text message. Here is the exception i am getting:
Exception in thread "main" java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source) at
sun.nio.cs.StreamDecoder.readBytes(Unknown Source) at
sun.nio.cs.StreamDecoder.implRead(Unknown Source) at
sun.nio.cs.StreamDecoder.read(Unknown Source) at
java.io.InputStreamReader.read(Unknown Source) at
java.io.BufferedReader.fill(Unknown Source) at
java.io.BufferedReader.readLine(Unknown Source) at
java.io.BufferedReader.readLine(Unknown Source) at
Q3.Client.main(Client.java:62)
If you want your client to do something when the server disconnects the connection, you need to do more than just catch SocketTimeoutException. As the stacktrace shows, a dropped connection will result in a generic SocketException being thrown. You should catch this also.
In other words, it looks like you are only handling the case where the initial connection to the server from the client fails; and you are not handling the case where an existing condition is dropped.
If the server is not responding to connect, your setSoTimeout will not cover that case, so make sure you have a timeout in the connection establishment code. Write this:
SocketAddress a = new InetSocketAddress(serverHostname, 10118);
echoSocket = new Socket();
echoSocket.connect(a, 10000);