in reply to Re^2: Port duplicator
in thread Port duplicator

The idea of using/creating a tee for ports is sound. The question remains on how to "best" implement it.

Let me first make a few definitions as I'm confusing the terms a bit:

Let the "remote server" be the machine that spews forth data on a single port. Let the "local server" be the program "tee for ports" you're trying to find/write. Let "client" be the program(s) that currently listen to the "remote server" but which you want to listen to the "local server".

As it seems that your machine will spew forth its data without interaction, I (personally) would prefer "prerecorded" test sessions that can be replayed to a client, more like cat for ports than tee, but that effect can be easily achieved by writing the spewed data to a file from a specialized client and then having a simple looping local server spew data from a file, both more or less using sysread. Such a thing could also be implemented using netcat I think.

So, let's now look at the premade wheels for a tee implementation. Let's assume that the clients will connect at an unspecified time and will also disconnect without telling the local server, likely because of a program crash. The local server should still serve the data to all remaining clients and not stall because one client isn't writeable anymore. Maybe it should also only store a fixed amount of data for any client before it considers the client dead, to prevent memory exhaustion.

As we don't want to stall, the simple use of IO::Tee won't work, as it will block if the data can't be written to a specific client immediately.

You could use threads together with Thread::Queue to distribute the incoming data from the remote server to all connected clients. This is likely the easiest way if you have a multithreaded Perl.

If you have an unthreaded Perl, you could look at creating a multiplex server using POE with POE::Component::Proxy::TCP and some tee-logic. Personally, I would avoid POE in this case and write my own multiplexer using select or IO::Select and do the buffering and distribution of packets manually.