Stream TCP Bridge
Rogue stream TCP bridging is provided by TcpServer and TcpClient. These
objects let a stream topology cross a TCP connection while preserving payload
bytes and Frame metadata.
You typically use the TCP bridge when the producer and consumer cannot live in the same process. Common cases include exporting a hardware-facing process to a remote analysis application, splitting acquisition and GUI work across two programs on the same machine, or moving a stream between computers without changing the rest of the stream graph.
Both ends of the bridge are bi-directional. A local Master can send
Frame objects to the remote side, and a local Slave can receive
Frame objects coming back in the other direction. In practice, that means a
single TCP bridge object can sit between local transmit and receive paths.
Bridge Behavior
Full-duplex stream transport
Uses two consecutive TCP ports
Preserves payload bytes and
FramemetadataSend path blocks when the remote side is absent or back-pressuring
Constructor Parameters
addr: forTcpServer, this is the local bind address or interface; forTcpClient, this is the remote server addressport: base port for the bridge; the implementation usesportandport + 1
Address And Port Mapping
Given base port P:
TcpServerbinds onPandP+1TcpClientconnects to the server onPandP+1
Python Server Example
The server side usually lives with the hardware-facing or locally owned stream endpoints.
import rogue.interfaces.stream as ris
# Local transmitter
src = MyCustomMaster()
# Local receiver
dst = MyCustomSlave()
# Listen on localhost using ports 8000 and 8001
tcp = ris.TcpServer('127.0.0.1', 8000)
# The local transmitter sends to the remote client, and the local receiver
# accepts data arriving from the remote client.
src >> tcp >> dst
Python Client Example
The client side usually runs in the remote or secondary process.
import rogue.interfaces.stream as ris
# Local transmitter
src = MyCustomMaster()
# Local receiver
dst = MyCustomSlave()
# Connect to the remote server using ports 8000 and 8001
tcp = ris.TcpClient('192.168.1.1', 8000)
# The local transmitter sends to the remote server, and the local receiver
# accepts data arriving from the remote server.
src >> tcp >> dst
C++ Server Example
#include "rogue/Helpers.h"
#include "rogue/interfaces/stream/TcpServer.h"
#include "MyCustomMaster.h"
#include "MyCustomSlave.h"
int main() {
// Local transmitter
auto src = MyCustomMaster::create();
// Local receiver
auto dst = MyCustomSlave::create();
// Listen on localhost using ports 8000 and 8001
auto tcp = rogue::interfaces::stream::TcpServer::create("127.0.0.1", 8000);
rogueStreamConnect(src, tcp);
rogueStreamConnect(tcp, dst);
return 0;
}
C++ Client Example
#include "rogue/Helpers.h"
#include "rogue/interfaces/stream/TcpClient.h"
#include "MyCustomMaster.h"
#include "MyCustomSlave.h"
int main() {
// Local transmitter
auto src = MyCustomMaster::create();
// Local receiver
auto dst = MyCustomSlave::create();
// Connect to the remote server using ports 8000 and 8001
auto tcp = rogue::interfaces::stream::TcpClient::create("192.168.1.1", 8000);
rogueStreamConnect(src, tcp);
rogueStreamConnect(tcp, dst);
return 0;
}
Loopback Process Split
The TCP bridge is also useful when two programs on the same machine need to
exchange stream traffic without sharing in-process Rogue objects. In that case,
use loopback addressing such as 127.0.0.1 and let one process publish a
TcpServer while the other connects with TcpClient.
This pattern is common when one process owns a hardware device and a second process performs analysis, logging, or UI work.
Logging
TcpCore uses Rogue C++ logging rather than Python logging. The logger
name is constructed dynamically from the address, mode, and port:
pyrogue.stream.TcpCore.<addr>.Server.<port>pyrogue.stream.TcpCore.<addr>.Client.<port>
Examples:
pyrogue.stream.TcpCore.127.0.0.1.Server.8000pyrogue.stream.TcpCore.192.168.1.1.Client.8000
Enable a broad filter before constructing the bridge if you want to see implementation messages:
import rogue
import rogue.interfaces.stream as ris
rogue.Logging.setFilter('pyrogue.stream.TcpCore', rogue.Logging.Debug)
tcp = ris.TcpClient('127.0.0.1', 8000)
You can also target one specific bridge instance when the full dynamic logger name is known.
Operational Notes
For a small number of bridges, the default operating-system limits are usually fine. For many parallel TCP bridge instances, file-descriptor and process limits may need to be tuned at the operating-system level.
During controlled shutdown paths, call stop() or close() where
appropriate so the bridge threads and sockets are released cleanly.
Resource Configuration For Multiple Streams
If a system needs to host many parallel TCP bridge instances, the limiting factor is often not Rogue itself but the operating-system resource limits around open files, sockets, threads, and memory mappings. The older stream documentation included a concrete Linux tuning example for this case, and that guidance is still useful when scaling to large numbers of bridges.
The example below was used on a Red Hat Enterprise Linux 7.9 machine to support the parallel launch of many TCP servers. The values are not universal tuning recommendations, but they illustrate the kinds of limits that may need to be raised.
Use sysctl to adjust system-wide limits such as open files, threads, and
memory maps:
sysctl -w fs.file-max=262140
sysctl -w kernel.threads-max=1014712
sysctl -w vm.max_map_count=2097152
Confirm the resulting values:
cat /proc/sys/fs/file-max
cat /proc/sys/kernel/threads-max
cat /proc/sys/vm/max_map_count
User-level process and file limits may also need to be increased. One way to do
that is by adding entries like the following to /etc/security/limits.conf:
* soft nproc 8192
* hard nproc 8192
* soft nofile 524280
* hard nofile 524280
After logging in again or otherwise reloading those limits, confirm the process
limits with ulimit -a and make sure values such as open files and
max user processes match the expected settings.
This section is intentionally operational rather than prescriptive. The exact values should be chosen for the target machine and workload, but if a large TCP bridge deployment behaves as though connections or worker threads are capped, operating-system limits are one of the first places to check.
What To Explore Next
Connection topology rules: Connecting Streams
Receive-side handling: Receiving Frames
Fifousage before a bridge: FIFO BufferingRateDropusage before a bridge: Rate Limiting With RateDrop