I have this damnable structure:
public void run() {
try {
if (!portField.getText().equals("")) {
String p = portField.getText();
CharSequence numbers = "0123456789";
btnRun.setEnabled(false);
if (p.contains(numbers)) {
ServerSocket listener = new ServerSocket(Integer.parseInt(p));
while (true) {
Socket socket = listener.accept();
try {
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.println("Hi there, human.");
} finally {
socket.close();
}
}} else {
JOptionPane.showMessageDialog(null, "Only numbers are allowed.");
}
}
} catch (NumberFormatException | HeadlessException | IOException e) {
e.printStackTrace();
}
}
As you can see, I need to close the listener exactly as I did with the socket. The problem is that if I try to do so after the loop the code will be "unreachable", and if I try to declare a field anywhere for the ServerSocket, I get a NullPointerException. I don't want to close the ServerSocket together with the socket/client because I want to make new connections.
So that's my question:
It's REALLY necessary to close the ServerSocket in this case? The ServerSocket closes itself by its own when the software is shut down? (System.exit(0)). If the ServerSocket continues to run when I close the software just because I have not closed it, then I have a problem, because I can't reach that bloody piece of code to close it :).
The Close method closes the remote host connection and releases all managed and unmanaged resources associated with the Socket. Upon closing, the Connected property is set to false . For connection-oriented protocols, it is recommended that you call Shutdown before calling the Close method.
If socket refers to an open TCP connection, the connection is closed. If a stream socket is closed when there is input data queued, the TCP connection is reset rather than being cleanly closed. The descriptor of the socket to be closed. Note: All sockets should be closed before the end of your process.
One way or another, if you don't close a socket, your program will leak a file descriptor. Programs can usually only open a limited number of file descriptors, so if this happens a lot, it may turn into a problem.
The close() method of ServerSocket class is used to close this socket. Any thread currently blocked in accept() will throw a SocketException. The associated channel is also closed by it if it has any.
Yes, it's necessary to release any finite resources, because otherwise your app will make other processes on the host starve for resources and won't be able to sustain in a long run
Here's how I do such task:
public void run() {
ServerSocket serverSocket = null;
try {
serverSocket = ... // init here
} catch (...) {
} finally {
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
// log error just in case
}
}
}
}
Additionally, moving GUI code to other class would be a nice idea, to keep things clean.
Yes. While destroying references to the socket may cause the garbage collector to finalize it, that does not specify that it will be closed. This is implementation-specific in many cases, and can sometimes derail relative to design due to performance or even minute bugs that are hard to track.
Keeping a reference anywhere is a sure bet that it won't be, even with WeakReferences.
Now the OS has a limited(due to its design) number of sockets it can give. As you open more and more sockets, the OS comes under pressure and eventually runs out of sockets, causing the failure of either Java or another program. In addition, depeding on socket options you or defaults may set, this socket may send keepalives, exhausting resources on the other endpoint as well.
On exit, it is closed by the socket registering a shutdown action in its constructor to close it, and/or the OS's automatic cleanup.
You should never rely on OS/JVM behavior or finalization to close your sockets, especially if you have multiple sockets, even if you don't plan to use all of them at the same time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With