转自https://blog.csdn.net/li_wen01/article/details/70260895
为了更加清晰的了解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
作者:li_wen01
来源:CSDN
原文:https://blog.csdn.net/li_wen01/article/details/70260895
版权声明:本文为博主原创文章,转载请附上博文链接!