![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/1c2aae9bc9774d6db98f65be443d1e87.png)
```c
1.1 创建Domain: ORTEDomainAppCreate
ORTEDomainAppCreate
-》ORTEDomainCreate(domain, prop, events, ORTE_FALSE)
sock_init_udp(&d->taskRecvUnicastMetatraffic.sock);
sock_init_udp(&d->taskRecvMulticastMetatraffic.sock);
sock_init_udp(&d->taskRecvUnicastUserdata.sock);
sock_init_udp(&d->taskRecvMulticastUserdata.sock);
sock_init_udp(&d->taskSend.sock);
appSelfParamChanged(d, ORTE_FALSE, ORTE_FALSE, ORTE_FALSE, ORTE_TRUE);
-》parameterUpdateCSChange(csChange, d->appParams, ORTE_TRUE);
-》CSTWriterAddCSChange(d, &d->writerApplicationSelf, csChange);
-》gavl_cust_for_each (CSTRemoteReader, cstWriter, cstRemoteReader)
-》ORTEDomainStart(d,
ORTE_TRUE,
d->domainProp.multicast.enabled,
ORTE_TRUE,
d->domainProp.multicast.enabled,
ORTE_TRUE)
-》ORTEDomainRecvThreadStart(&d->taskRecvUnicastMetatraffic)
ORTEDomainRecvThreadStart(&d->taskRecvMulticastMetatraffic)
ORTEDomainRecvThreadStart(&d->taskRecvUnicastUserdata)
ORTEDomainRecvThreadStart(&d->taskRecvMulticastUserdata)
ORTEDomainSendThreadStart(&d->taskSend)
-》pthread_create(&(tp->thread), NULL, (void *)&ORTEAppRecvThread, (void *)tp);
-》pthread_create(&(tp->thread), NULL, (void *)&ORTEAppSendThread, (void *)tp);
每一个本地的 cstWrite,均有一个或多个 RemoteReader,通过CSTWriterAddRemoteReader这个接口给一个cstWrite增加一个RemoteReader,那么该 cstWriter在发送消息时,将会给 RemoteReader对发送一份,有几个RemoteReader,就会发送几份
同样,每一个本地的 cstReader,均有一个或多个 RemoteWrite,通过CSTReaderAddRemoteWriter这个接口给一个cstReader增加一个RemoteWriter,那么该 cstReader在接收消息时,将会为每个 RemoteWriter接收一次,有几个RemoteWriter,就会接收几次
1.2 发送线程:ORTEAppSendThread
ORTEAppSendThread
-》htimerRoot_run_expired
-》timer->func(d, timer->objectEntryAID, pact_time);
eventAdd
-》fncNode->func = func;
-》htimerUnicastSendMetatraffic_update_root_timer(&d->objectEntry, objectEntryAID)
htimerUnicastSendMetatraffic_update_root_timer
-》objectEntryAID->htimUnicast.sendMetatrafficNode.func = htimerUnicastSendMetatraffic_run_expired;
-》htimerRoot_add(objectEntry, &objectEntryAID->htimUnicast.sendMetatrafficNode)
htimerUnicastSendMetatraffic_run_expired
-》ORTESendData
-》port = appParams->metatrafficUnicastPort;
-》des.sin_port = htons((uint16_t)port);
-》sock_sendto(&d->taskSend.sock,
d->taskSend.mb.cdrCodecDirect->buffer,
d->taskSend.mb.cdrCodecDirect->wptr,
&des,
sizeof(des))
1.3 接收线程:ORTEAppRecvThread
ORTEAppRecvThread
-》RTPS_Codec_len = sock_recvfrom(
&tp->sock,
cdrCodec->buffer,
cdrCodec->buf_len,
&des, sizeof(des))
-》recvfrom(sock->fd, buf, max_len, 0)
-》RTPSHeaderCheck(cdrCodec, RTPS_Codec_len, &mi)
-》switch ((SubmessageId)sub_id) {
case VAR:
RTPSVar(d, cdrCodec, &mi, ntohl(des.sin_addr.s_addr));
break;
case ACK:
RTPSAck(d, cdrCodec, &mi, ntohl(des.sin_addr.s_addr));
case HEARTBEAT:
RTPSHeartBeat(d, cdrCodec, &mi);
break;
1.4 注册topic: ORTETypeRegisterAdd
ORTETypeRegisterAdd
-》ORTEType_find(&d->typeEntry, &typeName)
-》ORTEType_insert(&d->typeEntry, tn)
1.5 创建发布者并周期发布消息:ORTEPublicationCreate
在创建domain时,会创建很多内置的CSTWriter:
CSTWriter writerPublications;
CSTReader readerPublications;
CSTWriter writerSubscriptions;
CSTReader readerSubscriptions;
当发布一个普通的topic前,会调用该函数创建一个新的CSTWriter *cstWriter
ORTEPublicationCreate
-》eventAdd(d,
objectEntryOID->objectEntryAID,
&objectEntryOID->sendCallBackDelayTimer,
0,
"PublicationCallBackTimer",
PublicationCallBackTimer,
&cstWriter->lock,
cstWriter,
&objectEntryOID->sendCallBackDelay);
-》CSTWriterInit(d, cstWriter, objectEntryOID, guid.oid, &cstWriterParams, &typeNode->typeRegister);
-》CSTWriter_insert(&d->publications, cstWriter);
-》parameterUpdateCSChangeFromPublication(csChange, pp);
parameterPutString(ps, PID_TOPIC, pp->topic);
CSChangeAttributes_insert(csChange, ps);
parameterPutString(ps, PID_TYPE_NAME, pp->typeName);
CSChangeAttributes_insert(csChange, ps);
-》CSTWriterAddCSChange(d, &d->writerPublications, csChange);
PublicationCallBackTimer
-》ORTEPublicationSendLocked(cstWriter, NULL)
-》CDR_codec_init_static(&csChange->cdrCodec)
-》RTPSHeaderCreate(&csChange->cdrCodec, cstWriter->domain->guid.hid, cstWriter->domain->guid.aid);
-》RTPSInfoTSCreate(&csChange->cdrCodec, getActualNtpTime());
-》RTPSIssueCreateHeader(&csChange->cdrCodec, 16+max_size, OID_UNKNOWN, cstWriter->guid.oid, snNext);
-》cstWriter->typeRegister->serialize(&csChange->cdrCodec, cstWriter->objectEntryOID->instance);
-》CDR_buffer_puts(&csChange->cdrCodec, cstWriter->objectEntryOID->instance, max_size);
-》CSTWriterAddCSChange(cstWriter->domain, cstWriter, csChange);
当manager收到一个APP发来的publish meta data时,进入到这里:
RTPSVarApp
-》case OID_WRITE_PUBL:
-》cstReader = &d->readerPublications;
-》cstRemoteWriter = CSTRemoteWriter_find(cstReader, writerGUID);
-》parameterUpdatePublication(csChange, pp);
-》PublicationList_insert(&d->psEntry, objectEntryOID);
-》debug(46, 2) ("new publisher 0x%x-0x%x-0x%x accepted\n",GUID_PRINTF(csChange->guid));
-》NewPublisher(d, objectEntryOID);
-》pnode->subscriptionCallBack ((char *) pp->topic,
(char *) pp->typeName,
pnode->param);
-》if ((strcmp((const char *)pp->topic, (const char *)sp->topic) == 0) &&
(strcmp((const char *)pp->typeName, (const char *)sp->typeName) == 0) &&
(pp->typeChecksum == sp->typeChecksum))
-》 cstReader = CSTReader_find(&d->subscriptions, &o->guid)
-》 CSTRemoteWriter_find(cstReader, &op->guid)
-》 CSTReaderAddRemoteWriter(d, cstReader, op, op->oid);
-》CSTReaderQueryTimer
-》RTPSAckCreate(
&d->taskSend.mb.cdrCodec,
&cstRemoteWriter->sn,
cstRemoteWriter->cstReader->guid.oid,
cstRemoteWriter->guid.oid,
ORTE_FALSE)
1.6 创建订阅者:ORTESubscriptionCreate
ORTESubscriptionCreate
-》strcpy ((char *) sp->topic, topic);
-》strcpy ((char *) sp->typeName, typeName);
-》objectEntryOID = objectEntryAdd (d, &guid, (void *) sp);
-》objectEntryOID->privateCreated = ORTE_TRUE;
-》objectEntryOID->instance = instance;
-》objectEntryOID->recvCallBack = recvCallBack;
-》objectEntryOID->callBackParam = recvCallBackParam;
-》CSTReaderInit (d, cstReader, objectEntryOID, guid.oid, &cstReaderParams, &typeNode->typeRegister);
-》CSTReader_insert (&d->subscriptions, cstReader);
-》parameterUpdateCSChangeFromSubscription (csChange, sp);
-》CSTWriterAddCSChange (d, &d->writerSubscriptions, csChange);
-》gavl_cust_for_each (CSTRemoteReader, cstWriter, cstRemoteReader)
{
eventAdd (d,
cstRemoteReader->sobject->objectEntryAID,
&cstRemoteReader->delayResponceTimer,
1,
"CSTWriterSendTimer",
CSTWriterSendTimer,
&cstRemoteReader->cstWriter->lock, cstRemoteReader,
NULL);
}
1.7 业务消息收发过程
1.7.1 发布者发布消息:
ORTEPublicationSendLocked
-》RTPSHeaderCreate (&csChange->cdrCodec,
cstWriter->domain->guid.hid,
cstWriter->domain->guid.aid);
-》RTPSInfoTSCreate (&csChange->cdrCodec, getActualNtpTime ());
-》RTPSIssueCreateHeader (&csChange->cdrCodec, 16 + max_size,
OID_UNKNOWN, cstWriter->guid.oid, snNext);
-》cstWriter->typeRegister->serialize (&csChange->cdrCodec,
cstWriter->objectEntryOID->
instance);
-》CSTWriterAddCSChange (cstWriter->domain, cstWriter, csChange)
-》gavl_cust_for_each (CSTRemoteReader, cstWriter, cstRemoteReader)
{
eventAdd (d,
cstRemoteReader->sobject->objectEntryAID,
&cstRemoteReader->delayResponceTimer,
1,
"CSTWriterSendTimer",
CSTWriterSendTimer,
&cstRemoteReader->cstWriter->lock, cstRemoteReader,
NULL);
}
-》CSTWriterSendTimer
-》gavl_cust_for_each (CSChangeForReader, cstRemoteReader, csChangeForReader)
1.7.2 订阅者接收消息:
RTPSIssue
-》gavl_cust_for_each (CSTReader, &d->subscriptions, cstReader)
-》cstRemoteWriter = CSTRemoteWriter_find (cstReader, &writerGUID);
-》CSTReaderProcCSChangesIssue
-》CSTReaderNewData (cstRemoteWriter, csChangeFromWriter)
-》cstRemoteWriter->cstReader->typeRegister->deserialize (&csChange->cdrCodec, objectEntryOID->instance)
-》objectEntryOID->recvCallBack (&info, objectEntryOID->instance, objectEntryOID->callBackParam)
1.8 关于端口号的分配:
对于 manager来说:
p = 7400 + d*10;
给d->taskRecvUnicastMetatraffic 指定端口: (7400 +d * 10)
对于普通app来说:
给d->taskRecvUnicastUserdata.sock , d->taskRecvUnicastMetatraffic, d->taskSend.sock 指定端口0,表示由系统自动分配一个可用的端口
1.9 关于内置端点
1.9.1 Common:
d->writerApplicationSelf
d->readerManagers
d->readerApplications
1.9.2 manager:
d->writerApplications
d->writerManagers
1.9.3 normal app:
d->writerPublications
d->writerSubscriptions
d->readerPublications
d->readerSubscriptions
1.9.4 内置的ID
#define OID_UNKNOWN 0x00000000
#define OID_APP 0x000001C1
#define OID_WRITE_APPSELF 0x000008C2
#define OID_READ_APPSELF 0x000008C7
#define OID_WRITE_APP 0x000001C2
#define OID_READ_APP 0x000001C7
#define OID_WRITE_MGR 0x000007C2
#define OID_READ_MGR 0x000007C7
#define OID_WRITE_PUBL 0x000003C2
#define OID_READ_PUBL 0x000003C7
#define OID_WRITE_SUBS 0x000004C2
#define OID_READ_SUBS 0x000004C7
1.10 RTPS消息
根据RTPS协议规范,RTPS Submessage中的INFO子消息可以分为以下几种类型:
INFO_TS:用于指示子消息的时间戳信息。它包含了一条时间戳,表示消息发送的时间。
INFO_SRC:用于指示消息发送者的身份信息。它包含了消息发送者的GUID(全局唯一标识符)和VendortID(供应商ID)。
INFO_REPLY_IP4:用于指示IPv4地址信息,以便消息接收方可以通过该地址进行回复。它包含了一个IPv4地址和端口号。
INFO_DST:用于指示消息的目标信息,包括消息接收方的主题识别符、实体ID和GUID等。它包含了一个Destination GUID Prefix(目标GUID前缀)和一个Entity ID(实体ID)。
INFO_REPLY:用于确认消息接收方是否成功接收了消息。它携带了一个Sequence Number Set(序列号集合),用于指示成功接收的消息序列号。
INFO_REQUEST:用于请求某些操作或数据。它携带了一个Sequence Number Set,用于指示请求的消息序列号。
INFO_REPLY_DELAY:用于指示回复延迟的时间间隔。它包含了一个Duration(延迟时间)。
INFO_HEARTBEAT:用于表示发布者或订阅者仍然处于活动状态,并且需要维护与其他实体之间的会话连接。它携带了一个First Sequence Number(起始序列号)和一个Last Sequence Number(最后序列号),用于描述当前发布者或订阅者的消息范围。
INFO_HEARTBEAT_FRAG:类似于INFO_HEARTBEAT,但用于传输分段数据。它携带了一个First Sequence Number和一个Last Sequence Number,以及分段数据的片段数量和索引。
INFO_DATA:用于传输实际的数据内容。该子消息通常包含序列号、内容数据和QoS(Quality of Service)信息等。它携带了一个Sequence Number(序列号)、一段数据内容和一些附加信息。
INFO_DATA_FRAG:类似于INFO_DATA,但用于传输分段数据。它携带了一个Sequence Number、分段数据的片段数量和索引,以及分段数据的片段内容。
INFO_ACKNACK:用于请求丢失的数据进行重传。它携带了一个Bitmap(位图),每个位表示一个消息序列号是否已经接收。
INFO_GAP:用于指示在序列号范围内缺失了哪些数据。它携带了一个Gap Start(缺失数据的起始序列号)和一个Gap List(缺失数据的序列号列表)。
这些是RTPS Submessage中INFO子消息的主要类型。具体使用哪些类型取决于具体的通信需求和协议配置。