6.3. TCP Transport¶
TCP is a connection oriented transport, so the DomainParticipant must establish a TCP connection to the remote peer before sending data messages. Therefore, one of the communicating DomainParticipants (the one acting as server) must open a TCP port listening for incoming connections, and the other one (the one acting as client) must connect to this port.
Note
The server and client concepts are independent from the DDS concepts of Publisher, Subscriber, DataWriter, and DataReader. Also, these concepts are independent from the eProsima Discovery Server servers and clients (Discovery Server Settings). Any of them can act as a TCP Server or TCP Client when establishing the connection, and the DDS communication will work over this connection.
Warning
This documentation assumes the reader has basic knowledge of TCP/IP concepts, since terms like Time To Live (TTL), Cyclic Redundancy Check (CRC), Transport Layer Security (TLS), socket buffers, and port numbering are not explained in detail. However, it is possible to configure a basic TCP transport on Fast DDS without this knowledge.
6.3.1. TCPTransportDescriptor¶
eProsima Fast DDS implements TCP transport for both TCPv4 and TCPv6.
Each of these transports is independent from the other, and has its own TransportDescriptorInterface
.
However, they share many of their features, and most of the TransportDescriptorInterface
data members are common.
The following table describes the common data members for both TCPv4 and TCPv6.
Member |
Data type |
Default |
Description |
---|---|---|---|
|
0 |
Size of the sending buffer of the socket (octets). |
|
|
0 |
Size of the receiving buffer of the socket (octets). |
|
|
|
See Netmask filtering. |
|
|
Empty vector |
List of allowed interfaces with |
|
|
Empty vector |
List of blocked interfaces. See Blocklist. |
|
|
Empty vector |
List of allowed interfaces See Interface Whitelist. |
|
|
1 |
Time to live, in number of hops. |
|
|
Empty vector |
List of ports to listen as server. If a port is set to 0, an available port will be automatically assigned. |
|
|
5000 |
Frequency of RTCP keep alive requests (in ms). |
|
|
15000 |
Time since sending the last keep alive request to consider a connection as broken (in ms). |
|
|
100 |
Maximum number of logical ports to try during RTCP negotiation. |
|
|
20 |
Maximum number of logical ports per request to try during RTCP negotiation. |
|
|
2 |
Increment between logical ports to try during RTCP negotiation. |
|
|
|
Enables the TCP_NODELAY socket option. |
|
|
|
Do not block on send operations (*). |
|
|
|
True to calculate and send CRC on message headers. |
|
|
|
True to check the CRC of incoming message headers. |
|
|
|
True to use TLS. See TLS over TCP. |
|
Configuration for TLS. See TLS over TCP. |
|||
Default ThreadSettings for the reception threads. |
|||
|
ThreadSettings for the reception threads on specific ports. |
||
ThreadSettings for the thread keeping alive TCP connections. |
|||
ThreadSettings for the threads processing incoming TCP connection requests. |
|||
|
0 |
Time to wait for logical port negotiation (in ms). If a logical port is under negotiation, it waits for the negotiation to finish up to this timeout before trying to send a message to that port. Setting this option to non-zero values increases the discovery time. Setting it to zero means no wait but could lead to loss of first messages. |
Warning
Although the member listening_ports
accepts multiple ports, only the first listening port
will be effectively used. The rest of the ports will be ignored.
Note
If listening_ports
is left empty, the participant will not be able to receive incoming
connections but will be able to connect to other participants that have configured their listening ports.
Note
When non_blocking_send
is set to true
, send operations will return immediately if the
send buffer might get full, but no error will be returned to the upper layer.
This means that the application will behave as if the packet is sent and lost.
When set to false
, send operations will block until the network buffer has space for the
packet.
6.3.1.1. TCPv4TransportDescriptor¶
The following table describes the data members that are exclusive for TCPv4TransportDescriptor
.
Member |
Data type |
Default |
Description |
---|---|---|---|
|
[0, 0, 0, 0] |
Configuration for WAN. See WAN or Internet Communication over TCPv4. |
Note
The kind
value for a TCPv4TransportDescriptor
is given by the value
LOCATOR_KIND_TCPv4
.
6.3.1.2. TCPv6TransportDescriptor¶
TCPv6TransportDescriptor
has no additional data members from the common ones described in
TCPTransportDescriptor.
Note
The kind
value for a TCPv6TransportDescriptor
is given by the value
LOCATOR_KIND_TCPv6
.
6.3.2. Enabling TCP Transport¶
There are several ways of enabling TCP transport in eprosima Fast DDS. According to the facet of each scenario, one method might suit better than the others.
6.3.2.1. Configuration of Builtin Transports¶
The first option is to modify the builtin transports that are responsible of the creation of the DomainParticipant
transports. The existing configuration that enables TCP transports is LARGE_DATA
.
This option instantiates a UDPv4, a TCPv4 and a SHM transport, respectively. UDP protocol will be used for multicast
announcements during the participant discovery phase (see Discovery phases) while the participant liveliness and
the application data delivery occurs over TCP or SHM. This configuration enables auto discovery and does not
require to manually set up each participant IP and listening port. Hence, avoiding the typical Server-Client
configuration.
Builtin Transports can be configured using the FASTDDS_BUILTIN_TRANSPORTS
environment variable (see
FASTDDS_BUILTIN_TRANSPORTS), XML profiles (see RTPS element type) or via code.
export FASTDDS_BUILTIN_TRANSPORTS=LARGE_DATA
<?xml version="1.0" encoding="UTF-8" ?>
<dds xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles">
<profiles>
<!--
UDP transport for PDP and SHM/TCPv4 transport for both EDP and application data
-->
<participant profile_name="large_data_builtin_transports" is_default_profile="true">
<rtps>
<builtinTransports>LARGE_DATA</builtinTransports>
</rtps>
</participant>
</profiles>
</dds>
eprosima::fastdds::dds::DomainParticipantQos qos;
qos.setup_transports(eprosima::fastdds::rtps::BuiltinTransports::LARGE_DATA);
Note
Note that LARGE_DATA
configuration of the builtin transports will also create a SHM transport along the UDP
and TCP transports. Shared Memory will be used whenever it is possible. Manual configuration will be required
if a TCP communication is required when SHM is feasible. (See Large Data Mode).
6.3.2.2. Server-Client Configuration¶
To set up a Server-Client configuration you need to create an instance of TCPv4TransportDescriptor (for TCPv4) or TCPv6TransportDescriptor (for TCPv6), and add it to the user transport list of the DomainParticipant.
Depending on the TCP transport descriptor settings and network locators defined, the DomainParticipant can act as a TCP Server or TCP Client.
TCP Server: If you provide
listening_ports
on the descriptor, the DomainParticipant will act as TCP server, listening for incoming remote connections on the given ports. The examples below show this procedure in both C++ code and XML file.eprosima::fastdds::dds::DomainParticipantQos qos; // Create a descriptor for the new transport. auto tcp_transport = std::make_shared<eprosima::fastdds::rtps::TCPv4TransportDescriptor>(); tcp_transport->add_listener_port(5100); // [OPTIONAL] ThreadSettings configuration tcp_transport->default_reception_threads(eprosima::fastdds::rtps::ThreadSettings{-1, 0, 0, -1}); tcp_transport->set_thread_config_for_port(12345, eprosima::fastdds::rtps::ThreadSettings{-1, 0, 0, -1}); tcp_transport->keep_alive_thread = eprosima::fastdds::rtps::ThreadSettings{-1, 0, 0, -1}; tcp_transport->accept_thread = eprosima::fastdds::rtps::ThreadSettings{-1, 0, 0, -1}; // Link the Transport Layer to the Participant. qos.transport().user_transports.push_back(tcp_transport); // Avoid using the default transport qos.transport().use_builtin_transports = false; // [OPTIONAL] Set unicast locators eprosima::fastrtps::rtps::Locator_t locator; locator.kind = LOCATOR_KIND_TCPv4; eprosima::fastrtps::rtps::IPLocator::setIPv4(locator, "192.168.1.10"); eprosima::fastrtps::rtps::IPLocator::setPhysicalPort(locator, 5100); // [OPTIONAL] Logical port default value is 0, automatically assigned. eprosima::fastrtps::rtps::IPLocator::setLogicalPort(locator, 5100); qos.wire_protocol().builtin.metatrafficUnicastLocatorList.push_back(locator); qos.wire_protocol().default_unicast_locator_list.push_back(locator);
<?xml version="1.0" encoding="UTF-8" ?> <dds> <profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles"> <transport_descriptors> <transport_descriptor> <transport_id>tcp_server_transport</transport_id> <type>TCPv4</type> <listening_ports> <port>5100</port> </listening_ports> <!-- Optional thread configuration --> <default_reception_threads> <scheduling_policy>-1</scheduling_policy> <priority>0</priority> <affinity>0</affinity> <stack_size>-1</stack_size> </default_reception_threads> <reception_threads> <reception_thread port="12345"> <scheduling_policy>-1</scheduling_policy> <priority>0</priority> <affinity>0</affinity> <stack_size>-1</stack_size> </reception_thread> </reception_threads> <keep_alive_thread> <scheduling_policy>-1</scheduling_policy> <priority>0</priority> <affinity>0</affinity> <stack_size>-1</stack_size> </keep_alive_thread> <accept_thread> <scheduling_policy>-1</scheduling_policy> <priority>0</priority> <affinity>0</affinity> <stack_size>-1</stack_size> </accept_thread> </transport_descriptor> </transport_descriptors> <participant profile_name="tcp_server_participant"> <rtps> <userTransports> <transport_id>tcp_server_transport</transport_id> </userTransports> <useBuiltinTransports>false</useBuiltinTransports> <!-- Optional unicast locator set --> <defaultUnicastLocatorList> <locator> <tcpv4> <address>192.168.1.10</address> <physical_port>5100</physical_port> <!-- Optional logical port set --> <port>5100</port> </tcpv4> </locator> </defaultUnicastLocatorList> <!-- Optional metatraffic unicast locator set --> <builtin> <metatrafficUnicastLocatorList> <locator> <tcpv4> <address>192.168.1.10</address> <physical_port>5100</physical_port> <!-- Optional logical port set --> <port>5100</port> </tcpv4> </locator> </metatrafficUnicastLocatorList> </builtin> </rtps> </participant> </profiles> </dds>
TCP Client: If you provide
initialPeersList
to the DomainParticipant, it will act as TCP client, trying to connect to the remote servers at the given addresses and ports. The examples below show this procedure in both C++ code and XML file. See Initial peers for more information about their configuration.eprosima::fastdds::dds::DomainParticipantQos qos; // Disable the built-in Transport Layer. qos.transport().use_builtin_transports = false; // Create a descriptor for the new transport. // Do not configure any listener port auto tcp_transport = std::make_shared<eprosima::fastdds::rtps::TCPv4TransportDescriptor>(); qos.transport().user_transports.push_back(tcp_transport); // [OPTIONAL] ThreadSettings configuration tcp_transport->default_reception_threads(eprosima::fastdds::rtps::ThreadSettings{-1, 0, 0, -1}); tcp_transport->set_thread_config_for_port(12345, eprosima::fastdds::rtps::ThreadSettings{-1, 0, 0, -1}); tcp_transport->keep_alive_thread = eprosima::fastdds::rtps::ThreadSettings{-1, 0, 0, -1}; tcp_transport->accept_thread = eprosima::fastdds::rtps::ThreadSettings{-1, 0, 0, -1}; // Set initial peers. eprosima::fastrtps::rtps::Locator_t initial_peer_locator; initial_peer_locator.kind = LOCATOR_KIND_TCPv4; eprosima::fastrtps::rtps::IPLocator::setIPv4(initial_peer_locator, "192.168.1.10"); eprosima::fastrtps::rtps::IPLocator::setPhysicalPort(initial_peer_locator, 5100); // If the logical port is set in the server side, it must be also set here with the same value. // If not set in the server side in a unicast locator, do not set it here. eprosima::fastrtps::rtps::IPLocator::setLogicalPort(initial_peer_locator, 5100); qos.wire_protocol().builtin.initialPeersList.push_back(initial_peer_locator);
<?xml version="1.0" encoding="UTF-8" ?> <dds> <profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles"> <transport_descriptors> <transport_descriptor> <transport_id>tcp_client_transport</transport_id> <type>TCPv4</type> <!-- Optional thread configuration --> <default_reception_threads> <scheduling_policy>-1</scheduling_policy> <priority>0</priority> <affinity>0</affinity> <stack_size>-1</stack_size> </default_reception_threads> <reception_threads> <reception_thread port="12345"> <scheduling_policy>-1</scheduling_policy> <priority>0</priority> <affinity>0</affinity> <stack_size>-1</stack_size> </reception_thread> </reception_threads> <keep_alive_thread> <scheduling_policy>-1</scheduling_policy> <priority>0</priority> <affinity>0</affinity> <stack_size>-1</stack_size> </keep_alive_thread> <accept_thread> <scheduling_policy>-1</scheduling_policy> <priority>0</priority> <affinity>0</affinity> <stack_size>-1</stack_size> </accept_thread> </transport_descriptor> </transport_descriptors> <participant profile_name="tcp_client_participant"> <rtps> <userTransports> <transport_id>tcp_client_transport</transport_id> </userTransports> <useBuiltinTransports>false</useBuiltinTransports> <builtin> <initialPeersList> <locator> <tcpv4> <address>192.168.1.10</address> <physical_port>5100</physical_port> <!-- To be set if set in server --> <port>5100</port> </tcpv4> </locator> </initialPeersList> </builtin> </rtps> </participant> </profiles> </dds>
Note
Manually setting unicast locators is optional. If not setting them or setting them with a logical
port of 0
, the client’s initial peer shouldn’t set its logical port (or set it to 0
). Otherwise,
initial peer’s logical port must match server’s unicast logical port.
HelloWorldExampleTCP shows how to use and configure a TCP transport.
6.3.3. WAN or Internet Communication over TCPv4¶
Fast DDS is able to connect through the Internet or other WAN networks when configured properly. To achieve this kind of scenarios, the involved network devices such as routers and firewalls must add the rules to allow the communication.
For example, imagine we have the scenario represented on the following figure:
A DomainParticipant acts as a TCP server listening on port
5100
and is connected to the WAN through a router with public IP80.80.99.45
.Another DomainParticipant acts as a TCP client and has configured the server’s IP address and port in its Initial peers list.
By using set_WAN_address(wan_ip)
, the WAN IP address is set on the participant’s locators that
are communicated during the discovery phase.
Like in the LAN case, manually setting unicast locators is optional. However, in this case, there are some considerations to take into account when setting its IP addresses:
Setting the WAN IP address using the
setWAN()
method in unicast locators is ineffective because it gets overridden by theset_WAN_address()
call.For assigning IP addresses to unicast locators, use only the
setIPv4()
orsetIPv6()
methods, which are LAN IP setters. There are some configurations which allow using these setters with a WAN IP address.
Depending on whether the server has manually set its metatraffic unicast locators and default unicast locators, the client needs to adjust its initial peer list accordingly:
If the server’s unicast locators are configured with the LAN IP address:
The initial peer can be set up with only the server’s WAN IP using the LAN IP setter.
Alternatively, it can be configured with both the server’s LAN and WAN IP addresses using the LAN setter for the LAN IP and the WAN setter for the WAN IP.
If the server’s unicast locators are configured with the WAN IP address:
The initial peer must be set up with only the server’s WAN IP using the LAN setter.
Alternatively, it can be configured with the WAN IP address using both the LAN and WAN setters.
If the server has not set any unicast locators:
The initial peer can be configured with only the server’s WAN IP using the LAN setter.
Alternatively, it can be configured with both the server’s LAN and WAN IP addresses using the LAN setter for the LAN IP and the WAN setter for the WAN IP.
Note
Manually setting unicast locators is optional. If not setting them or setting them with a logical
port of 0
, the client’s initial peer shouldn’t set its logical port (or set it to 0
). Otherwise,
initial peer’s logical port must match server’s unicast logical port.
On the server side, the router must be configured to forward to the TCP server
all traffic incoming to port 5100
. Typically, a NAT routing of port 5100
to our
machine is enough. Any existing firewall should be configured as well.
In addition, to allow incoming connections through a WAN,
the TCPv4TransportDescriptor must indicate its public IP address
in the wan_addr
data member.
The following examples show how to configure the DomainParticipant both in C++ and XML.
eprosima::fastdds::dds::DomainParticipantQos qos;
// Create a descriptor for the new transport.
auto tcp_transport = std::make_shared<eprosima::fastdds::rtps::TCPv4TransportDescriptor>();
tcp_transport->add_listener_port(5100);
tcp_transport->set_WAN_address("80.80.99.45");
// [OPTIONAL] ThreadSettings configuration
tcp_transport->default_reception_threads(eprosima::fastdds::rtps::ThreadSettings{-1, 0, 0, -1});
tcp_transport->set_thread_config_for_port(12345, eprosima::fastdds::rtps::ThreadSettings{-1, 0, 0, -1});
tcp_transport->keep_alive_thread = eprosima::fastdds::rtps::ThreadSettings{-1, 0, 0, -1};
tcp_transport->accept_thread = eprosima::fastdds::rtps::ThreadSettings{-1, 0, 0, -1};
// Link the Transport Layer to the Participant.
qos.transport().user_transports.push_back(tcp_transport);
// Avoid using the default transport
qos.transport().use_builtin_transports = false;
// [OPTIONAL] Set unicast locators (do not use setWAN(), set_WAN_address() overwrites it)
eprosima::fastrtps::rtps::Locator_t locator;
locator.kind = LOCATOR_KIND_TCPv4;
// [RECOMMENDED] Use the LAN address of the server
eprosima::fastrtps::rtps::IPLocator::setIPv4(locator, "192.168.1.10");
// [ALTERNATIVE] Use server's WAN address. In that case, initial peers must be configured
// only with server's WAN address.
// eprosima::fastrtps::rtps::IPLocator::setIPv4(locator, "80.80.99.45");
eprosima::fastrtps::rtps::IPLocator::setPhysicalPort(locator, 5100);
// [OPTIONAL] Logical port default value is 0, automatically assigned.
eprosima::fastrtps::rtps::IPLocator::setLogicalPort(locator, 5100);
qos.wire_protocol().builtin.metatrafficUnicastLocatorList.push_back(locator);
qos.wire_protocol().default_unicast_locator_list.push_back(locator);
<?xml version="1.0" encoding="UTF-8" ?>
<dds>
<profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles">
<transport_descriptors>
<transport_descriptor>
<transport_id>tcp_server_wan_transport</transport_id>
<type>TCPv4</type>
<listening_ports>
<port>5100</port>
</listening_ports>
<wan_addr>80.80.99.45</wan_addr>
<!-- Optional thread configuration -->
<default_reception_threads>
<scheduling_policy>-1</scheduling_policy>
<priority>0</priority>
<affinity>0</affinity>
<stack_size>-1</stack_size>
</default_reception_threads>
<reception_threads>
<reception_thread port="12345">
<scheduling_policy>-1</scheduling_policy>
<priority>0</priority>
<affinity>0</affinity>
<stack_size>-1</stack_size>
</reception_thread>
</reception_threads>
<keep_alive_thread>
<scheduling_policy>-1</scheduling_policy>
<priority>0</priority>
<affinity>0</affinity>
<stack_size>-1</stack_size>
</keep_alive_thread>
<accept_thread>
<scheduling_policy>-1</scheduling_policy>
<priority>0</priority>
<affinity>0</affinity>
<stack_size>-1</stack_size>
</accept_thread>
</transport_descriptor>
</transport_descriptors>
<participant profile_name="tcp_server_wan_participant">
<rtps>
<userTransports>
<transport_id>tcp_server_wan_transport</transport_id>
</userTransports>
<useBuiltinTransports>false</useBuiltinTransports>
<!-- Optional unicast locator set -->
<defaultUnicastLocatorList>
<locator>
<tcpv4>
<address>192.168.1.10</address>
<!-- Alternatively use WAN address -->
<!-- <address>80.80.99.45</address> -->
<physical_port>5100</physical_port>
<!-- Optional logical port set -->
<port>5100</port>
</tcpv4>
</locator>
</defaultUnicastLocatorList>
<!-- Optional metatraffic unicast locator set -->
<builtin>
<metatrafficUnicastLocatorList>
<locator>
<tcpv4>
<address>192.168.1.10</address>
<!-- Alternatively use WAN address -->
<!-- <address>80.80.99.45</address> -->
<physical_port>5100</physical_port>
<!-- Optional logical port set -->
<port>5100</port>
</tcpv4>
</locator>
</metatrafficUnicastLocatorList>
</builtin>
</rtps>
</participant>
</profiles>
</dds>
On the client side, the DomainParticipant must be configured
with the public IP address and listening_ports
of the TCP server as
Initial peers.
eprosima::fastdds::dds::DomainParticipantQos qos;
// Disable the built-in Transport Layer.
qos.transport().use_builtin_transports = false;
// Create a descriptor for the new transport.
// Do not configure any listener port
auto tcp_transport = std::make_shared<eprosima::fastdds::rtps::TCPv4TransportDescriptor>();
// [RECOMMENDED] Use client's WAN address if there are more clients in other local networks.
tcp_transport->set_WAN_address("80.80.99.47");
qos.transport().user_transports.push_back(tcp_transport);
// [OPTIONAL] ThreadSettings configuration
tcp_transport->default_reception_threads(eprosima::fastdds::rtps::ThreadSettings{-1, 0, 0, -1});
tcp_transport->set_thread_config_for_port(12345, eprosima::fastdds::rtps::ThreadSettings{-1, 0, 0, -1});
tcp_transport->keep_alive_thread = eprosima::fastdds::rtps::ThreadSettings{-1, 0, 0, -1};
tcp_transport->accept_thread = eprosima::fastdds::rtps::ThreadSettings{-1, 0, 0, -1};
// Set initial peers.
eprosima::fastrtps::rtps::Locator_t initial_peer_locator;
initial_peer_locator.kind = LOCATOR_KIND_TCPv4;
// [RECOMMENDED] Use both WAN and LAN server addresses
eprosima::fastrtps::rtps::IPLocator::setIPv4(initial_peer_locator, "192.168.1.10");
eprosima::fastrtps::rtps::IPLocator::setWan(initial_peer_locator, "80.80.99.45");
// [ALTERNATIVE] Use server's WAN address only. Valid if server specified its unicast locators
// with its LAN or WAN address.
// eprosima::fastrtps::rtps::IPLocator::setIPv4(initial_peer_locator, "80.80.99.45");
eprosima::fastrtps::rtps::IPLocator::setPhysicalPort(initial_peer_locator, 5100);
// If the logical port is set in the server side, it must be also set here with the same value.
// If not set in the server side in a unicast locator, do not set it here.
eprosima::fastrtps::rtps::IPLocator::setLogicalPort(initial_peer_locator, 5100);
qos.wire_protocol().builtin.initialPeersList.push_back(initial_peer_locator);
<?xml version="1.0" encoding="UTF-8" ?>
<dds>
<profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles">
<transport_descriptors>
<transport_descriptor>
<transport_id>tcp_client_wan_transport</transport_id>
<type>TCPv4</type>
<!-- Recommended client's WAN set -->
<wan_addr>80.80.99.47</wan_addr>
<!-- Optional thread configuration -->
<default_reception_threads>
<scheduling_policy>-1</scheduling_policy>
<priority>0</priority>
<affinity>0</affinity>
<stack_size>-1</stack_size>
</default_reception_threads>
<reception_threads>
<reception_thread port="12345">
<scheduling_policy>-1</scheduling_policy>
<priority>0</priority>
<affinity>0</affinity>
<stack_size>-1</stack_size>
</reception_thread>
</reception_threads>
<keep_alive_thread>
<scheduling_policy>-1</scheduling_policy>
<priority>0</priority>
<affinity>0</affinity>
<stack_size>-1</stack_size>
</keep_alive_thread>
<accept_thread>
<scheduling_policy>-1</scheduling_policy>
<priority>0</priority>
<affinity>0</affinity>
<stack_size>-1</stack_size>
</accept_thread>
</transport_descriptor>
</transport_descriptors>
<participant profile_name="tcp_client_wan_participant">
<rtps>
<userTransports>
<transport_id>tcp_client_wan_transport</transport_id>
</userTransports>
<useBuiltinTransports>false</useBuiltinTransports>
<builtin>
<initialPeersList>
<locator>
<tcpv4>
<!-- Recommended use of both WAN and LAN server addresses -->
<wan_address>80.80.99.45</wan_address>
<address>192.168.1.10</address>
<!-- Alternatively use server's WAN addresses only -->
<!-- <address>80.80.99.45</address> -->
<physical_port>5100</physical_port>
<!-- To be set if set in server -->
<port>5100</port>
</tcpv4>
</locator>
</initialPeersList>
</builtin>
</rtps>
</participant>
</profiles>
</dds>
6.3.4. HelloWorldExampleTCP¶
A TCP version of helloworld example can be found in the HelloWorldExampleTCP folder. It shows a publisher and a subscriber that communicate through TCP. The publisher is configured as TCP server while the Subscriber is acting as TCP client.