poidl
poidl

Reputation: 453

How can I reuse a server-side TCP endpoint for multiple consumers?

I'm a beginner trying to understand TCP, and I'm using Rust. If I create a new listener and bind it to an address

let tcplistener = TcpListener::bind("127.0.0.1:55555").unwrap();

I can tcplistener.accept() new connections between 127.0.0.1:55555 and some other endpoint on the client.

In my case, tcplistener lives within an instance of a struct representing a plugin. Each plugin should be controllable from its own browser tab. There is one connection (endpoint-pair) per plugin, with one endpoint always being 127.0.0.1:55555. The plugins run in a single thread with non-blocking listeners and streams. I use websockets, but I'm not sure if this question is specific to websockets.

What I'm doing now is

This seems to work; if I instantiate a new plugin B afterwards, I can create a listener bound to 127.0.0.1:55555 and accepting a connection. If I don't create a new listener with different address/port, then I get the "Address already in use" error.

This is obviously not a good solution since it occupies all the other ports for no reason. Is there a better way?

A comment said:

Why does each plugin have a TcpListener? Why not have one component with the listener, call accept, then hand off the returned TcpStream to each constructed plugin?

That does sound good, but where would that TcpListener be stored, and how does it hand off the streams? Possibilities I see for storing:

Upvotes: 1

Views: 563

Answers (1)

Shepmaster
Shepmaster

Reputation: 431369

One workaround, if I understand all of your limitations correctly, is to use Option. Option is used for precisely the case of "something or not something".

Here, you could have an Option<TcpListener>. On a freshly-initialized plugin, this would be set to Some(...), and once accepted, would transition to None.

This does have a number of downsides:

  • There's a time period where there are no listeners.
  • You have to deal with the possibility of the listener being None.
  • You can't start a second plugin before the first one accepts something.

Some kind of parent-child relationship is probably better, or even limiting to a singleton plugin, if plausible.

Upvotes: 1

Related Questions