godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
88.74k stars 20.12k forks source link

Expose reuse_port option in PacketPeer #49090

Closed hruf-inmusic closed 2 years ago

hruf-inmusic commented 3 years ago

Godot version: 3.2.3

OS/device including version: Win10/OSX

Issue description: I'm writing an application that needs to listen to a specific UDP port non-exclusively. Depending on the network configuration of the machine this sometimes works, sometimes it doesn't (PacketPeerUDP returning ERR_UNAVAILABLE). After lots of digging in the engine code I found the required option in the NetSocketPosix implementation: set_reuse_port_enabled(). Unfortunately it is not part of the NetSocket interface and not accessible from PacketPeerUDP. Please do either expose it or enable it per default in PacketPeerUDP::listen() as done with set_reuse_address_enabled(true).

Chaosus commented 3 years ago

3.2.3

this version is old and no longer supported - please check if this issue is relevant to the latest version? (3.3.2)

hruf-inmusic commented 3 years ago

I've updated to 3.3.2 and the problem still exists. Only difference: PacketPeerUDP::listen() does not call NetSocket::set_reuse_address_enabled(true) anymore but that seems to be unrelated.

Chaosus commented 3 years ago

сс @Faless

Faless commented 3 years ago

@hruf-inmusic do you have any details on the use case? It's rarely a good idea to bind sockets which allows reusing the address:port combination.

hruf-inmusic commented 3 years ago

I'm writing an Art-Net client. Although it's a network protocol a typical use case is different programs communicating on the same machine. Since it always uses the same port, conflicts are unfortunately a common problem. I have tested my implementation on two different windows machines. I worked fine on the one with a loopback adapter installed, but PacketPeerUDP::listen() fails on the other machine without loopback adapter.

mhilbrunner commented 2 years ago

a typical use case is different programs communicating on the same machine Enabling port reuse likely won't solve this problem. One way is to add a way to configure the port used at runtime, or to negotiate that in some way on the local machine, depending on specifics. You could check whether the port is used and fallback to a different one, choose a random port, use UPnP or save used ports somewhere locally, or use mutexes/semaphores. You could also have a broker process responsible for allocating/managing ports and telling every process involved which ports are in used and where to reach each process.

I'm going to close this, as there is not a huge response to this feature request so far. However, you may want to open a proposal trough the official proposal process in the proposals repository to gauge interest and discuss use cases there. See: https://godotengine.org/article/introducing-godot-proposals-repository

lighttroupe commented 3 months ago

+1 for this feature.

Use case: an interactive-visuals designer/player made in Godot 4 (yet to be released) that receives OpenSoundControl data over UDP from various sources (DAWs, music players, hardware devices, TouchOSC on ipads, etc.).

While it's not typical to run two instances of the app on one computer, it is supported for end-users (eg driving different visuals on multiple projectors), and also a common practice during development (using Godot's own Debug > Run Multiple Instances feature) for testing multiplayer. When this happens, only the first instance can receive UDP packets with input data.

I'd appreciate if PacketPeerUDP exposed set_reuse_port_enabled.

AThousandShips commented 3 months ago

As clarified above this should be made in the proposals repo, if you're interested please open a proposal, otherwise this issue is closed and this isn't the place for proposals

lighttroupe commented 3 months ago

For future reference:

I was able to open two UDP listeners on one port (in Godot 4 on Ubuntu) by changing from using PacketPeerUDP (using bind) to UDPServer (using listen) as shown in this PR conversation.

Then, in the sender, enabling UDP broadcast flag on the socket, and sending to a broadcast IP.

Multiple receivers then see a new "connection" and receive the same packets.