I’m working on Client-Server simulation in Java where Clients (threads) are connecting to server to get some data. After several seconds, one of randomly chosen client (thread) needs to be killed. I close socket it used for communication to server and left him die (by exiting from run() method). Problem is when new created thread is trying to create same socket as previous one used (same addresses and same ports) to connect to server, I’m getting:
java.net.BindException: Address already in use
at java.net.PlainSocketImpl.socketBind(Native Method)
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:374)
at java.net.Socket.bind(Socket.java:627)
at java.net.Socket.<init>(Socket.java:423)
at java.net.Socket.<init>(Socket.java:319)
Code for creating socket:
private void createNewSocket(InetAddress sIP, int sPort,
InetAddress cIP, int cPort) {
try {
socket = new Socket(sIP, sPort, cIP, cPort);
} catch (IOException e) {
e.printStackTrace();
System.err.println("Socket unsuccessfully created");
}
try {
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream())), true);
} catch (IOException e) {
e.printStackTrace();
try {
socket.close();
} catch (IOException e2) {
System.err.println("Socket unsuccessfully closed");
}
}
}
public void run() {
createNewSocket(gprsServerIP, Util.PORT_SERVER_PORT,
clientIP, sendPort);
out.println(REQUEST);
try {
serverPort = Integer.parseInt(in.readLine());
TCPClient.serverPort[clientID] = serverPort;
System.out.println("Server port: " + serverPort + '\n' +
"Send port: " + sendPort + '\n');
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
System.err.println("Socket unsuccessfully closed");
}
}
while (true) {
if (clientID == TCPClient.selectedID) {
TCPClient.selectedID = -1;
createNewSocket(gprsServerIP, Util.PORT_SERVER_PORT,
clientIP, sendPort);
out.println(FREE_PORT + serverPort);
try {
socket.close();
} catch (IOException e2) {
System.err.println("Socket unsuccessfully closed");
}
//System.out.println(socket.isClosed());
System.out.println("Port:" + serverPort + " is free");
TCPClient.id[clientID] = -1;
break;
}
}
clientCount--;
}
Chances are that the client socket is still either in
CLOSE_WAITorTIME_WAITstatus. The operating system is making sure that all data has been delivered down the socket before another application can re-use it. Otherwise, the new client might get garbage duplicate packets left over from the previous connection.I would suggest that your clients work with a range of ports instead of a constant. Then they can use the next port in the range and loop around when they reach the end of the range.
However, if you don’t need to set the client port then you should not set the client port in your code at all by passing in a port of 0 to
Socket. In this case the, JDK and the operating system will do the right thing and choose an appropriate free port for you.Quoted from wikipedia: