最简RTSP客户端程序设计

 

  为了更加清晰的了解RTSP协议,本文设计了一个最简的RTSP客户端程序,该程序向RTSP 依次发送OPTIONS, DESCRIBE, SETUP, PLAY , TEARDOWN请求,以查看服务端返回的数据。同时建立RTP和RTCP 通信,接收一包RTP和一包RTCP数据包。

说明:

    服务端程序:live555 testProgs 中的 testH264VideoStreamer

    服务端地址:192.168.0.6

    多播地址    :232.231.110.2

    RTP端口    :18888

    RTCP端口 :18889

    客户端地址:192.168.0.5

部分代码如下:

/*============================================================================= 
#     FileName: rtspRequest.c
#         Desc: client connect to RTSP server
#       Author: licaibiao 
#   LastChange: 2017-04-19  
=============================================================================*/ 
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>

#define MAXBUF 1024

void Handel_OPTION(char *inbuffer);
void Handel_DESCRIBE(char *inbuffer, int sockfd);
void Handel_SETUP(char *inbuffer, int sockfd);
void Handel_PLAY(char *inbuffer, int sockfd,char *sessionId);
void Handle_PAUSE(char *inbuffer,int sockfd, char *sessionId);
void Handel_Teardown(char *inbuffer, int sockfd,char *sessionId);


int   intsearch(char * buf, char * searchStr, int len);
int   strsearch(char * buf, char * searchStr, int len,char *dest);
int   init_udpsocket(int port, struct sockaddr_in *servaddr, char *mcast_addr);
void  release_udpsocket(int socket_fd, char *mcast_addr);
void  proc_udpsocket(int socket_fd, struct sockaddr_in servaddr,int flag);
	
char sendOPTRequstStr[] = "OPTIONS rtsp://192.168.0.6:8554/testStream RTSP/1.0\r\n";
char userAgentStr[] = "virtual client player\r\n";
char successfullyReplyStr[] = "RTSP/1.0 200 OK\r\n";
char sendDESRequstStr[] = "DESCRIBE rtsp://192.168.0.6:8554/testStream RTSP/1.0\r\n";
char sendSETUPRequstStr[] = "SETUP rtsp://192.168.0.6:8554/testStream/track1 RTSP/1.0\r\n";
char sendPLAYRequstStr[] = "PLAY rtsp://192.168.0.6:8554/testStream/ RTSP/1.0\r\n";
char sendTeardownRequestStr[]="TEARDOWN rtsp://192.168.0.6:8554/testStream/ RTSP/1.0\r\n";
char sendPauseRequestStr[]="PAUSE rtsp://192.168.0.6:8554/testStream/ RTSP/1.0\r\n";
char CseqHeadStr[] = "Cseq: ";					
char UserHeadStr[] = "User-Agent: ";			
char ApplicationHeadStr[] = "Accept: ";			
char TransportHeadStr[] = "Transport: ";       
char SessionHeadStr[] = "Session: ";           
char RangeHeadStr[] = "Range: ";				
int cseqCount=0;

int main(int argc, char **argv)
{
    int sockfd,rtpsockfd,rtcpsockfd, len;
    struct sockaddr_in dest;      
	struct sockaddr_in RTPAddr;
    struct sockaddr_in RTCPAddr;
	char serverIP[]="192.168.0.6";
	char mcast_addr[] = "232.231.110.2"; 
    char buffer[MAXBUF + 1] = {0};
	int	serverPort=8554;
    int udpPort=0;

    cseqCount=0;
		
    /* creat socket for rtsp */
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {      
        perror("Socket");
        exit(errno);
    }
    printf("socket created\n");

    /* init server add and port */
    bzero(&dest, sizeof(dest));
    dest.sin_family = AF_INET;     
    dest.sin_port   = htons(serverPort);    
    if (inet_pton(AF_INET, serverIP, &dest.sin_addr) < 0 ) {           
        perror(serverIP);
        exit(errno);
    }
    printf("address created\n");

    /* connect to server */
    if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) {
        perror("Connect error\n");
        exit(errno);
    }
    printf("server connected\n");

    /* MAXBUF use to receive message from stream server */
    bzero(buffer, MAXBUF + 1);

	/* send message to server */
	Handel_OPTION(buffer);
    len = send(sockfd, buffer, strlen(buffer), 0);
    if (len < 0)
        printf("OPTION Reply Msg:\n %s send error! error code is %d, error content is  %s \n", buffer, errno, strerror(errno));
    else
        printf("OPTION Reply Msg:\n %s send successfully,total content is %d bytes!\n", buffer, len);
	bzero(buffer, MAXBUF + 1);
	
    /* receive message from server */
    len = recv(sockfd, buffer, MAXBUF, 0); /* OPTION Reply */
    if (len < 0){
        printf("OPTION Reply Msg:\n %s receive error! error code is %d, error content is  %s \n", buffer, errno, strerror(errno));		
	}
    else{
        printf("OPTION Reply Msg:\n %s receive successfully,total content is %dbytes!\n", buffer, len);		
	}

	
	if (memcmp(buffer, successfullyReplyStr, sizeof(successfullyReplyStr) -1) == 0){
		Handel_DESCRIBE(buffer, sockfd);
	}
	else{
		printf("the OPTION answer Msg is wrong!\n");
		return 0;
	}
	
	bzero(buffer, MAXBUF + 1);
    /* DESCRIBE Reply */
    len = recv(sockfd, buffer, MAXBUF, 0);
    if (len < 0){
        printf("DESCRIBE Reply Msg:\n %s receive error! error code is %d, error content is  %s \n", buffer, errno, strerror(errno));		
	}
    else{
        printf("DESCRIBE Reply Msg:\n %s receive successfully,total content is %dbytes!\n", buffer, len);		
	}

	if (memcmp(buffer, successfullyReplyStr, sizeof(successfullyReplyStr)-1) == 0){
		Handel_SETUP(buffer, sockfd);		
	}
	else{
		printf("the DESCRIBE answer Msg is wrong!\n");
		return 0;
	}
	
	bzero(buffer, MAXBUF + 1);    
    len = recv(sockfd, buffer, MAXBUF, 0);
    if (len < 0){
	    printf("SETUP Reply Msg:\n %s receive error! error code is %d, error content is  %s \n", buffer, errno, strerror(errno));
	}
    else{
		printf("SETUP Reply Msg:\n %s receive successfully,total content is %dbytes!\n", buffer, len);
	}
       
	char sessionIdTmp[30];
	bzero(sessionIdTmp,sizeof(sessionIdTmp));

	strsearch(buffer, "Session: ", 9, sessionIdTmp);
	if (memcmp(buffer, successfullyReplyStr, sizeof(successfullyReplyStr)-1) == 0)
	{
		char searchStrTmp[13]="port=";
		udpPort=intsearch(buffer,searchStrTmp,5);
		if(udpPort==0){
			return 0;
		}
		printf("the udp port is %d\n",udpPort);
		
		bzero(&RTPAddr,sizeof(RTPAddr));
		bzero(&RTCPAddr,sizeof(RTCPAddr));
		
		rtpsockfd  = init_udpsocket(udpPort, &RTPAddr, mcast_addr);
		rtcpsockfd = init_udpsocket(udpPort+1, &RTCPAddr, mcast_addr);
	
		Handel_PLAY(buffer, sockfd,sessionIdTmp);
	}
	else
	{
		printf("the SETUP answer Msg is wrong!\n");
		return 0;
	}
	
	bzero(buffer, MAXBUF + 1);
	len = recv(sockfd, buffer, MAXBUF, 0);
    if (len < 0){	
		printf("PLAY Reply Msg:\n %s receive error! error code is %d, error content is  %s \n", buffer, errno, strerror(errno));	
	}else{
		printf("PLAY Reply Msg:\n %s receive successfully,total content is %dbytes!\n", buffer, len);
	}
        
	if (memcmp(buffer, successfullyReplyStr, sizeof(successfullyReplyStr)-1) != 0){
		printf("the play answer Msg is wrong!\n");
		return 0;
	}
	
	bzero(buffer, MAXBUF + 1);
	printf("now,receiving RTP packets data......\n");
	proc_udpsocket(rtpsockfd, RTPAddr, 0);
	proc_udpsocket(rtcpsockfd, RTCPAddr, 1);
	
	Handle_PAUSE(buffer, sockfd, sessionIdTmp);
	
	len = recv(sockfd, buffer, MAXBUF, 0);
    if(len < 0){
		printf("PAUSE Reply Msg:\n %s receive error! error code is %d, error content is  %s \n", buffer, errno, strerror(errno));
	} 
    else{
		printf("PAUSE Reply Msg:\n %s receive successfully,total content is %dbytes!\n", buffer, len);
	}
        

	if (memcmp(buffer, successfullyReplyStr, sizeof(successfullyReplyStr)-1) != 0){
		printf("the pause answer Msg is wrong!\n");
		return 0;
	}
	
	bzero(buffer, MAXBUF + 1);
	Handel_Teardown(buffer, sockfd,sessionIdTmp);
	len = recv(sockfd, buffer, MAXBUF, 0);
    if (len < 0){
		printf("teardown Reply Msg:\n %s receive error! error code is %d, error content is  %s \n", buffer, errno, strerror(errno));	
	}  
    else{
		printf("teardown Reply Msg:\n %s receive successfully,total content is %dbytes!\n", buffer, len);
	}
        
	release_udpsocket(rtpsockfd, mcast_addr);
	release_udpsocket(rtcpsockfd, mcast_addr);
    return 0;
}

    编译运行结果如下:

licaibiao@lcb:~/test/RTSP$ gcc rtspRequest.c -o test
licaibiao@lcb:~/test/RTSP$ ./test 
socket created
address created
server connected
OPTION Reply Msg:
 OPTIONS rtsp://192.168.0.6:8554/testStream RTSP/1.0
Cseq: 1
User-Agent: virtual client player

 send successfully,total content is 99 bytes!
OPTION Reply Msg:
 RTSP/1.0 200 OK
CSeq: 1
Date: Thu, Apr 20 2017 07:27:32 GMT
Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETER

 receive successfully,total content is 152bytes!
DESCRIBE Request Msg:
 DESCRIBE rtsp://192.168.0.6:8554/testStream RTSP/1.0
Cseq: 2
Accept: application/sdp
User-Agent: virtual client player

 send successfully,total content is 125 bytes!
DESCRIBE Reply Msg:
 RTSP/1.0 200 OK
CSeq: 2
Date: Thu, Apr 20 2017 07:27:32 GMT
Content-Base: rtsp://192.168.0.6:8554/testStream/
Content-Type: application/sdp
Content-Length: 589

v=0
o=- 1492673143011076 1 IN IP4 192.168.0.6
s=Session streamed by "testH264VideoStreamer"
i=test.264
t=0 0
a=tool:LIVE555 Streaming Media v2017.04.10
a=type:broadcast
a=control:*
a=source-filter: incl IN IP4 * 192.168.0.6
a=rtcp-unicast: reflection
a=range:npt=0-
a=x-qt-text-nam:Session streamed by "testH264VideoStreamer"
a=x-qt-text-inf:test.264
m=video 18888 RTP/AVP 96
c=IN IP4 232.231.110.2/255
b=AS:500
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1;profile-level-id=640015;sprop-parameter-sets=Z2QAFazZQeCmwEQAAAMBkAAAL2g8WLZY,aOvssiw=
a=control:track1
 receive successfully,total content is 757bytes!
SETUP Request Msg:
 SETUP rtsp://192.168.0.6:8554/testStream/track1 RTSP/1.0
Cseq: 3
Transport: RTP/AVP;unicast;client_port=31126-31127
User-Agent: virtual client player

 send successfully,total content is 156 bytes!
SETUP Reply Msg:
 RTSP/1.0 200 OK
CSeq: 3
Date: Thu, Apr 20 2017 07:27:32 GMT
Transport: RTP/AVP;multicast;destination=232.231.110.2;source=192.168.0.6;port=18888-18889;ttl=255
Session: 75BF219C;timeout=65

 receive successfully,total content is 195bytes!
the udp port is 18888
PLAY Request Msg:
 PLAY rtsp://192.168.0.6:8554/testStream/ RTSP/1.0
Cseq: 4
Session: 75BF219C
Range: npt=0.000-
User-Agent: virtual client player

 send successfully,total content is 135 bytes!
PLAY Reply Msg:
 RTSP/1.0 200 OK
CSeq: 4
Date: Thu, Apr 20 2017 07:27:32 GMT
Range: npt=0.000-
Session: 75BF219C
RTP-Info: url=rtsp://192.168.0.6:8554/testStream/track1;seq=53244;rtptime=3158552668

 receive successfully,total content is 189bytes!
now,receiving RTP packets data......
Recv 1024 Byte RTP message from server
Recv 48 byte RTCP message from server,they are :
  o T   f    e  Q ( f    o T   u b u n t u     

PAUSE Request Msg:
 PAUSE rtsp://192.168.0.6:8554/testStream/ RTSP/1.0
Cseq: 5
Session: 75BF219C
User-Agent: virtual client player

 send successfully,total content is 117 bytes!
PAUSE Reply Msg:
 RTSP/1.0 200 OK
CSeq: 5
Date: Thu, Apr 20 2017 07:27:33 GMT
Session: 75BF219C

-Agent: virtual client player

 receive successfully,total content is 84bytes!
TEARDOWN Request Msg:
 TEARDOWN rtsp://192.168.0.6:8554/testStream/ RTSP/1.0
Cseq: 6
Session: 75BF219C
User-Agent: virtual client player

 send successfully,total content is 120 bytes!
teardown Reply Msg:
 RTSP/1.0 200 OK
CSeq: 6
Date: Thu, Apr 20 2017 07:27:33 GMT

ession: 75BF219C
User-Agent: virtual client player

 receive successfully,total content is 65bytes!
licaibiao@lcb:~/test/RTSP$ 


完整的工程代码下载路径:https://download.csdn.net/download/li_wen01/9820375

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

li_wen01

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值