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).
Related
In the client-server socket program below, the client is sending data to server which is listening on port 3500, but here the server is not sending any data back to client, so in the client socket program, i do not read from then input stream then am getting socket exception, socket write error.
below is the server code:
private static ServerSocket sc = null;
private static final int port = 3500;
public static void main(String args[]) throws IOException{
try {
sc = new ServerSocket(port);
while(true){
Socket socket = sc.accept();
System.out.println("Listening on port <=> "+port);
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
String message = (String) ois.readObject();
System.out.println("Received Request <=>"+message);
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject("Hi Client received your message<=>"+message);
ois.close();
oos.close();
socket.close();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Client socket code below:
try {
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
Socket clientsocket = null;
for(int i=0;i<2;i++){
clientsocket = new Socket(InetAddress.getLocalHost().getHostName(), 3500);
oos = new ObjectOutputStream(clientsocket.getOutputStream());
oos.writeObject("Client Request: "+i);
//ois = new ObjectInputStream(clientsocket.getInputStream());
//String message = (String) ois.readObject();
//System.out.println("Message sent by Server: " + message);
//ois.close();
oos.close();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
In the above code, if the comments are removed then the code is working fine, but confused why the input stream should be read when there is no data to be read.
Getting below exception after commenting the input stream section as done above.
Listening on port <=> 3500
Received Request <=>Client Request: 0
java.net.SocketException: Software caused connection abort: socket write error
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(Unknown Source)
at java.net.SocketOutputStream.write(Unknown Source)
at java.io.ObjectOutputStream$BlockDataOutputStream.drain(Unknown Source)
at java.io.ObjectOutputStream$BlockDataOutputStream.setBlockDataMode(Unknown Source)
at java.io.ObjectOutputStream.writeNonProxyDesc(Unknown Source)
at java.io.ObjectOutputStream.writeClassDesc(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeFatalException(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at com.springexercise.demo.ServerTest.main(ServerTest.java:28)
The error is because you close the connection on the client side before the server has a chance to write data into the stream.
If you remove the
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject("Hi Client received your message<=>"+message);
....
oos.close();
part the error should be resolved because the server is no longer trying to write on a closed connection.
If you have the client reading part in the code the whole process works because the client wait for new data in the connection. That leads to the situation where the connection is still open when the server tries to write and everything is working as expected from the java site.
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;
}
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.
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);