Fix for Port Binding Conflicts in ArtNetClient and ArtNetServer
This PR addresses an issue (#26) where the ArtNetClient and ArtNetServer classes were causing port binding conflicts when used as a sender and receiver simultaneously on the same machine. By introducing a new parameter to control whether the client/server should bind to a port or use an ephemeral port, we resolve the conflicts and improve the flexibility of the library.
Changes Made:
-
ArtNetClient.java:
- Added a new
start(boolean isReceiver)method to allow specifying the mode (sender or receiver) directly. - Modified existing
startmethods to preserve backward compatibility and default to using the input buffer to determine the receiver mode.
- Added a new
-
ArtNetServer.java:
- Updated the
startmethod to accept aboolean isReceiverparameter to control whether to bind to the specified port or use an ephemeral port.
- Updated the
Testing:
- Tested with Processing 4 application to ensure the
ArtNetClientcan be started as a sender usingartnet.start(false). - Verified that no port binding conflicts occur when running multiple instances as both sender and receiver on the same machine.
Documentation:
Usage Example:
To start an ArtNetClient as a sender (without port binding):
import ch.bildspur.artnet.*;
ArtNetClient artnet;
byte[] dmxData = new byte[512];
void setup() {
size(500, 250);
colorMode(HSB, 360, 100, 100);
textAlign(CENTER, CENTER);
textSize(20);
// create artnet client without buffer (no receiving needed)
artnet = new ArtNetClient(null);
artnet.start(false); // false indicates it is a sender
}
void draw() {
// create color
int c = color(frameCount % 360, 80, 100);
background(c);
// fill dmx array
dmxData[0] = (byte) red(c);
dmxData[1] = (byte) green(c);
dmxData[2] = (byte) blue(c);
// send dmx to localhost
artnet.unicastDmx("127.0.0.1", 0, 0, dmxData);
// show values
text("R: " + (int)red(c) + " Green: " + (int)green(c) + " Blue: " + (int)blue(c), width / 2, height / 2);
}
Backward Compatibility:
- The existing methods are preserved to maintain backward compatibility.
- The new parameter defaults to
truefor receiver mode when not specified.
Conclusion:
These changes improve the flexibility and usability of the artnet4j library by resolving port binding conflicts and allowing users to specify the mode of the client/server.
I really needed this behavior for my own application so I didn't go too deeply into an optimal fix. A better solution may be to infer if the connection is a reciever or sender somehow, but this was beyond the limits of what I had time for and to be honest my Java is not that great.
If the maintainers feel like this solution is adequate though, great!
All the best,
-T
You know what... this commit is not suitable for main branch after testing and thinking through further.
This commit would cause a breaking change and require updating existing code beacuse passing null into .start() results in the server launching in ephemeral mode.
Sorry I didn't catch this before sending the PR. I will close for now and push another one that retains the pre-existing behavior when start() is passed with a null value.
Fixing the issue now it's a one line change.
Alright, it's safe now.
Hey Tyler, thanks for creating this PR. I apologize for my late response. The project isn’t as important to me as it used to be. To be honest, I’m not satisfied with my API design that combines both the sender and receiver in a single class. While it was done for simplicity in mind for Processing users, I believe I should have chosen a different approach.
Anyway, thanks for the additional option. I’ll merge it now. The release of a new library could be delayed, so you could use jitpack until then.
No worries, and totally understandable.
I wasn't sure if this was an nice enough solution to the problem and it felt more like a hack/workaround to me, but if it helps anyone stuck in a similar position I suppose it's worth it.
Thanks for all the work on artnet4j @cansik - it powered us through some fantastic light shows out here last year 🙌