Hello,
im writing a simple program using the Processing Net library, this program should be able to start/stop a TCP server on a given port.
I have noticed that calling voluntarily the stop() function i receive in the console output the following message :
Server SocketException: socket closed
test case :
import processing.net.*;
Server server;
void setup()
{
size(200, 200);
try
{
server = new Server(this, 3273);
}
catch (Exception exception) {println("PORT ALREADY IN USE");};
}
void draw()
{
background(color(0,0,0));
}
/******************************/
void keyTyped()
{
server.stop();
}
This package is built when building Processing. For a short immediate solution if this was an isolated library, one could rebuild it with the single line change aka. removing the print() statement. For this case, I think you would need to re-build Processing. This could be easier than just trying to figure out what java files you need to modify related to the processing.net package. Maybe it is not difficult to isolate them but I haven’t tried that before.
For a better and long term solution, you could submit a ticket in github. However, it might take some time before they provide a solution.
On a side note, the message shows up in the console. An easier approach is to ignore the messages all together. I mean, it is not interfering with your code or demonstrations, or is it?
IMO, library devs do a big disservice to the Processing community (who are very tweaky by nature ) by using the keyword private or leaving the default package access level.
As we can confirm from class Server’s source code:
Both fields thread & server were left as package-protected access level. And many other fields as well btW!
We could use reflection to force access to them all. But it’s too convoluted & a hassle!
A much clever workaround is to make a “.java” file for our “hacked” Server subclass, which is HServer.
And then “lie” that the “HServer.java” file belongs to package “processing.net” too!
All of a sudden all those package-protected members become accessible to our custom HServer subclass!
Here’s my take on that:
“HServer.java”
package processing.net;
import java.io.IOException;
import processing.core.PApplet;
public class HServer extends Server {
public HServer(PApplet parent, int port) {
this(parent, port, null);
}
public HServer(PApplet parent, int port, String host) {
super(parent, port, host);
}
@Override public void dispose() {
thread = null;
if (clients != null) {
disconnectAll();
clientCount = 0;
clients = null;
}
try {
if (server != null) {
server.close();
server = null;
}
}
catch (final IOException e) {
//e.printStackTrace();
}
}
}
However, the red message “Server SocketException: socket closed” still shows up!
Your assumption that commenting out e.printStackTrace(); within method dispose() would get rid of it is wrong!
According to the comment right there at the SocketExceptioncatch () {} block within method run():
Thrown when server.close(); is called and server is waiting on accept().
Method dispose() invokes server.close(); right here:
However, there’s nothing we can do from within Server::dispose(), b/c ServerSocket::close() method always throws a SocketException when ServerSocket::accept() is active:
@kfrajer@GoToLoop first of all thanks to both of you for your time .
Ill try to explaine a little more my “weird” question and the solution i have found after your suggestions
CASE SCENARIO :
the thread is blocked waiting on accept()
an socket exception is thrown
QUESTION :
Who has launched the exception ?
ANSWER :
it’s me stopping the server —> OK, dont print nothing we know it
it is a real network problem —> ERROR, print the stack trace
As you can see my goal is to distinguish two separate cases and handle them of consequence .
As suggested i worked on the HServer.java file and extended the class.
As solution i added a boolean variable named “stopIsRequested” and overrided stop() and run() method with minimal difference from the original source code as follow :
package processing.net;
import processing.core.*;
import java.io.*;
import java.lang.reflect.*;
import java.net.*;
public class HServer extends Server
{
boolean stopIsRequested ;
public HServer(PApplet parent, int port)
{
this(parent, port, null);
}
public HServer(PApplet parent, int port, String host)
{
super(parent, port, host);
}
@Override public void stop()
{
this.stopIsRequested = true ;
dispose();
}
@Override public void run() {
this.stopIsRequested = false;
while (Thread.currentThread() == thread) {
try {
Socket socket = server.accept();
Client client = new Client(parent, socket);
synchronized (clientsLock) {
addClient(client);
if (serverEventMethod != null) {
try {
serverEventMethod.invoke(parent, this, client);
} catch (Exception e) {
System.err.println("Disabling serverEvent() for port " + port);
Throwable cause = e;
// unwrap the exception if it came from the user code
if (e instanceof InvocationTargetException && e.getCause() != null) {
cause = e.getCause();
}
cause.printStackTrace();
serverEventMethod = null;
}
}
}
} catch (SocketException e) {
//thrown when server.close() is called and server is waiting on accept
if( ! stopIsRequested ) { System.err.println("Server SocketException: " + e.getMessage()); };
thread = null;
} catch (IOException e) {
//errorMessage("run", e);
e.printStackTrace();
thread = null;
}
}
}
}
You are right !
unfortunatly in one of the costructor of the original server class there is :
96: parent.registerMethod(“dispose”, this);
and according to processing documentation :
public void dispose() {
// Anything in here will be called automatically when
// the parent sketch shuts down. For instance, this might
// shut down a thread used by this library.
}
But then, if the sketch is closed by the user, rather than by an explicit call to Server::stop(), that red “Server SocketException: socket closed” message is displayed if the flag isn’t set within Server::dispose()!
I was under the impression you wanted to eliminate that message if there’s no actual error.
The way your version is set up, normal sketch closing always results in that message error.