欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 创投人物 > fastdds:传输层端口号计算规则

fastdds:传输层端口号计算规则

2025/4/2 8:47:58 来源:https://blog.csdn.net/weixin_38184628/article/details/146771534  浏览:    关键词:fastdds:传输层端口号计算规则

当使用UDP或者SHM作为传输层时,我们经常看到7400、7410、7411、7412这些端口号。

那么这些端口号是怎么计算出来的?又有什么用呢?

如下图所示,使用fastdds中的例子delivery_mechanisms,指定传输层为UDPv4,启动了两个publisher。启动的第一个publisher使用了端口号7400、7410、7411,第二个publisher使用了端口号7400、7412、7413。

dds流量有两类:发现流量和用户流量。发现流量(PDP/EDP)用于particiapant以及eriter/reader之间的发现;用户流量用于收发用户数据。

 

发现流量需要用到多播和单播。发现流量是用户流量的基础,只有相互发现的writer/reader之间才能够进行数据传输。发现流量作为dds工作的基础和发起点,发现流量没有前置条件,所以在同一个domain内,发现流量多播端口号需要时众所周知的。

发现流量:多播端口=PB + DG * domainId + d0

 其中PB是portBase,DG是domainIdGain,d0取值为0。

多播端口只受domaiId影响,所以在同一个domain内的所有participant均使用相同的多播端口,这也说明只有在同一个domain内的participant才能相互发现。

每一个participant创建之后,都要通过多播的方式想多播组内发布自己的信息。发现过程除了使用多播,还会使用单播。假如一个domain内有3个participant,分别为A、B、C。假如A发布的多播消息,那么B和C都会收到,如果B和A之间有相同topic的writer和reader,也就是说B和A是可以通信的,那么B就会向A发送单播消息,进行后续的协商,后边的协商过程均通过单播来实现。这里跟tcp建立连接的过程是有些相似的,tcp建立连接时,客户端需要向服务端发起连接,tcp服务端接收连接请求的是监听套接字,这个套接字类似与多播流量;当监听套接字收到连接请求后,会在创建一个新的套接字与客户端形成连接,后边的用户流量都通过新的套接字来进行。

发现流量:单播端口=PB + DG * domainId + d1 + PG * participantId

如果domainId是0,participantId也是0,那么发现流量的多播端口是7400,单播端口是7410。在函数RTPSParticipantImpl::createReceiverResources中,首先使用7410端口进行绑定,如果失败,那么会进行重试,重试就是重新选择一个新的端口来使用。在函数RTPSParticipantImpl::applyLocatorAdaptRule中选择新的端口,选择新的端口的算法就是在端口的基础上加上delta,默认情况下delta是2。

单播端口也不完全由domainId和participantId来决定。participantId的分配如下代码所示,同一个进程的同一个domain内,participantId都是从0开始的,也就是说participantId并不是domain内唯一的,而是domain和进程内唯一的。

如果我们使用udp传输层,但是publisher和subscriber在同一台机器上的两个进程中,那么两者的participantId都是0,那么两个进程都要使用单播端口7410吗?这样显然是不对的。

uint32_t RTPSDomainImpl::getNewId()

{

    // Get the smallest available participant ID.

    // Settings like maxInitialPeersRange control how many participants a peer

    // will look for on this host.

    // Choosing the smallest value ensures peers using unicast discovery will

    // find this participant as long as the total number of participants has

    // not exceeded the number of peers they will look for.

    uint32_t i = 0;

    while (m_RTPSParticipantIDs[i].reserved || m_RTPSParticipantIDs[i].used)

    {

        ++i;

    }

    m_RTPSParticipantIDs[i].reserved = true;

    return i;

}

bool RTPSParticipantImpl::createReceiverResources(

        LocatorList_t& Locator_list,

        bool ApplyMutation,

        bool RegisterReceiver,

        bool log_when_creation_fails)

{

   ...

    for (auto it_loc = input_list.begin(); it_loc != input_list.end(); ++it_loc)

    {

        Locator_t loc = *it_loc;

        bool ret = m_network_Factory.BuildReceiverResources(loc, newItemsBuffer, max_receiver_buffer_size);

        if (!ret && ApplyMutation)

        {

            uint32_t tries = 0;

            while (!ret && (tries < m_att.builtin.mutation_tries))

            {

                tries++;

                applyLocatorAdaptRule(loc);

                ret = m_network_Factory.BuildReceiverResources(loc, newItemsBuffer, max_receiver_buffer_size);

            }

        }

        ...

}

Locator_t& RTPSParticipantImpl::applyLocatorAdaptRule(

        Locator_t& loc)

{

    // This is a completely made up rule

    // It is transport responsibility to interpret this new port.

    uint16_t delta = m_att.port.participantIDGain;

    if (metatraffic_unicast_port_ == loc.port)

    {

        metatraffic_unicast_port_ += delta;

    }

    loc.port += delta;

    return loc;

}

 

一般情况下,用户的流量使用单播来进行,计算公式如下。同样的,如果单播端口已经被占用,那么就会进行重试,重试的算法是在上一个端口的基础上加2。

用户流量:单播端口=PB + DG * domainId + d3 + PG * participantId

 

这样我们就能知道下图中的端口分别是做什么用的了:

7400:两个进程的都会使用的组播端口,用于发现流量

7410:5013进程发现流量的单播端口

7411:5013进程用户流量的单播端口

 

7412:5025进程发现流量的单播端口

7413:5025进程用户流量的单播端口

 

共享内存借用UDP中端口的概念,还是使用例子delivery_mechanisms,指定传输层是SHM,在/dev/shm下可以看到如下文件,其中7400、7410、7411、7412、7413也是用来标记通信的端口。

 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词