在我們使用live555作爲RTSP服務器時,客戶端在rtp over udp模式下, rtsp客戶端沒有發送teardown而直接斷開連接時需要等待65秒纔回調關閉的問題。
分析問題
在RTSPClientConnection中沒有保存相應的session值, 所以在RTSPClientConnection斷開時, 並沒有刪除相應的RTSPClientSession;
解決問題
在RTSPClientConnection的聲明中,增加以下定義;
char fClientSessionIdStr[16]; //for rtp over udp
GenericMediaServer.hh 增加createNewClientSessionWithId的參數char *pSessionIdStr
ClientSession* createNewClientSessionWithId(UsageEnvironment *pEnv, char *pSessionIdStr);
GenericMediaServer::ClientSession* GenericMediaServer::createNewClientSessionWithId(UsageEnvironment *_pEnv, char *pSessionIdStr) {
u_int32_t sessionId;
char sessionIdStr[16] = {0};
// Choose a random (unused) 32-bit integer for the session id
// (it will be encoded as a 8-digit hex number). (We avoid choosing session id 0,
// because that has a special use by some servers.)
do {
sessionId = (u_int32_t)our_random32();
snprintf(sessionIdStr, sizeof sessionIdStr, "%08X", sessionId);
} while (sessionId == 0 || lookupClientSession(sessionIdStr) != NULL);
ClientSession* clientSession = createNewClientSession(sessionId, _pEnv);
if (clientSession != NULL) fClientSessions->Add(sessionIdStr, clientSession);
if (NULL != pSessionIdStr) strcpy(pSessionIdStr, sessionIdStr); //此處返回生成的sessionId, 後續要根據該值找到對應的ClientSession
return clientSession;
}
void RTSPServer::RTSPClientConnection::handleRequestBytes(int newBytesRead, UsageEnvironment *pEnv) {
//找到以下代碼
if (authenticationOK("SETUP", urlTotalSuffix, (char const*)fRequestBuffer)) {
memset(fClientSessionIdStr, 0x00, sizeof(fClientSessionIdStr));
clientSession
= (RTSPServer::RTSPClientSession*)fOurRTSPServer.createNewClientSessionWithId(pEnv, fClientSessionIdStr); //此處記錄ClientSession的sessionId
}
}
此時,在RTSPClientConnection中已經保存了對應的SessionId, 在客戶端斷開連接時, 可以根據該SessionId, 找到相應的ClientSession, 然後刪除;
void RTSPServer::stopTCPStreamingOnSocket(UsageEnvironment *pEnv, int socketNum, int *clientTrackNum, char *clientSessionIdStr){
// Close any stream that is streaming over "socketNum" (using RTP/RTCP-over-TCP streaming):
RTSPClientSession *pClientSession = NULL;
LockClientConnection();
do
{
streamingOverTCPRecord* sotcp
= (streamingOverTCPRecord*)fTCPStreamingDatabase->Lookup((char const*)socketNum);
if (sotcp != NULL) { //rtp over tcp
do {
RTSPClientSession* clientSession
= (RTSPServer::RTSPClientSession*)lookupClientSession(sotcp->fSessionId);
if (clientSession != NULL) {
//clientSession->SetAssignSink(assignSink);
clientSession->deleteStreamByTrack(pEnv, sotcp->fTrackNum, False, clientTrackNum);
}
streamingOverTCPRecord* sotcpNext = sotcp->fNext;
sotcp->fNext = NULL;
delete sotcp;
sotcp = sotcpNext;
} while (sotcp != NULL);
fTCPStreamingDatabase->Remove((char const*)socketNum);
}
else if ( (clientTrackNum) && (*clientTrackNum==0)) //rtp over udp
{
pClientSession = (RTSPServer::RTSPClientSession*)lookupClientSession(clientSessionIdStr);
}
}while (0);
UnlockClientConnection();
if (pClientSession != NULL) //pClientSession不爲空, 說明爲rtp over udp
{
delete pClientSession;
}
}