前言
GB28181规范指定了RTP over TCP采用的协议格式
RFC 4571: Framing Real-time Transport Protocol (RTP) and RTP Control Protocol (RTCP) Packets over Connection-Oriented Transport ()
代码实现
源码rtptcptransmitter.cpp
int RTPTCPTransmitter::SendRTPRTCPData(const void *data, size_t len)
{
if (!m_init)
return ERR_RTP_TCPTRANS_NOTINIT;
MAINMUTEX_LOCK
if (!m_created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_TCPTRANS_NOTCREATED;
}
if (len > RTPTCPTRANS_MAXPACKSIZE)
{
MAINMUTEX_UNLOCK
return ERR_RTP_TCPTRANS_SPECIFIEDSIZETOOBIG;
}
std::map<SocketType, SocketData>::iterator it = m_destSockets.begin();
std::map<SocketType, SocketData>::iterator end = m_destSockets.end();
vector<SocketType> errSockets;
int flags = 0;
#ifdef RTP_HAVE_MSG_NOSIGNAL
flags = MSG_NOSIGNAL;
#endif // RTP_HAVE_MSG_NOSIGNAL
while (it != end)
{
uint8_t lengthBytes[2] = { (uint8_t)((len >> 8)&0xff), (uint8_t)(len&0xff) };
SocketType sock = it->first;
if (send(sock,(const char *)lengthBytes,2,flags) < 0 ||
send(sock,(const char *)data,len,flags) < 0)
errSockets.push_back(sock);
++it;
}
MAINMUTEX_UNLOCK
if (errSockets.size() != 0)
{
for (size_t i = 0 ; i < errSockets.size() ; i++)
OnSendError(errSockets[i]);
}
// Don't return an error code to avoid the poll thread exiting
// due to one closed connection for example
return 0;
}
相关代码
while (it != end)
{
uint8_t lengthBytes[2] = { (uint8_t)((len >> 8)&0xff), (uint8_t)(len&0xff) };
SocketType sock = it->first;
if (send(sock,(const char *)lengthBytes,2,flags) < 0 ||
send(sock,(const char *)data,len,flags) < 0)
errSockets.push_back(sock);
++it;
}
代码分析
外层循环,遍历每一个目标主机的套接字准备发送数据,先构建准备发送数据包长度的缓存lengthBytes,先发送两个字节长度的缓存,然后才真正发送真实的数据包,符合RFC4571标准
抓包分析
0030 20 00 2b 5b 00 00 80 60 0d 99 04 e6 47 07 88 23 .+[...`....G..#
0040 8e b5 00 00 01 ba 44 00 04 04 e4 01 00 03 ff f8 ......D.........
0050 04 cf 80 60 0d 9a 04 e6 55 17 88 23 8e b5 00 00 ...`....U..#....
0060 01 e0 04 bd 80 c0 0a 31 00 03 6d a1 11 00 03 6d .......1..m....m
参考例子
JRTPLIB/tcptest.cpp at master · j0r1/JRTPLIB · GitHub