artnet4j icon indicating copy to clipboard operation
artnet4j copied to clipboard

Fix for Port Binding Conflicts in ArtNetClient and ArtNetServer

Open tylerstraub opened this issue 1 year ago • 3 comments

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:

  1. ArtNetClient.java:

    • Added a new start(boolean isReceiver) method to allow specifying the mode (sender or receiver) directly.
    • Modified existing start methods to preserve backward compatibility and default to using the input buffer to determine the receiver mode.
  2. ArtNetServer.java:

    • Updated the start method to accept a boolean isReceiver parameter to control whether to bind to the specified port or use an ephemeral port.

Testing:

  • Tested with Processing 4 application to ensure the ArtNetClient can be started as a sender using artnet.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 true for 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

tylerstraub avatar May 31 '24 06:05 tylerstraub

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.

tylerstraub avatar May 31 '24 06:05 tylerstraub

Fixing the issue now it's a one line change.

tylerstraub avatar May 31 '24 07:05 tylerstraub

Alright, it's safe now.

tylerstraub avatar May 31 '24 07:05 tylerstraub

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.

cansik avatar Apr 24 '25 18:04 cansik

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 🙌

tylerstraub avatar Apr 25 '25 07:04 tylerstraub