RTSP调试代码

来源:互联网 发布:旧版手机淘宝2014安卓 编辑:程序博客网 时间:2024/06/05 17:42

#ifdef _WIN32_WCE#include "stdafx.h"#endif#ifndef _WIN32_WCE#define WIN32_LEAN_AND_MEAN#endif#include <windows.h>#include <commctrl.h>#include <MMSystem.h>#include <winsock2.h>#include <stdio.h>#include <stdlib.h>#include <tchar.h>#ifdef _WIN32_WCE#pragma comment(lib, "ws2.lib")#else#pragma comment(lib, "ws2_32.lib")#endif#define  PP_NAME "User-Agent: rtsp client(v1.0)"#define  PP_CRLF "\r\n"//打开连接;long InitSocket();//关闭连接;long DeInitSocket();//初始化tcp socket;long InitTCPSocket(int port);//初始化udp socket;long InitUDPSocket(const char *ip, int port);//取socket端口号;long GetSokcetPort(int sock, int *port);//读取数据;long ReadSocket(int sock, char *buf, int len, int timeout);//发送命令数据;long SendRTSPCmd(int sock, const char *cmd, const char *szparam);//解析rtsp命令回应数据;long PraseRTSPCmd();long PraseOptionCmd(const char *sz);long PraseDescribeCmd(const char *sz);long PraseSetupCmd(const char *sz, char *sess);long PrasePlayCmd(const char *sz);long GetResponseCode(const char *sz);  //取返回值;////////////////////////////////////////////////////////////////////////////字符串操作函数;static char* getLine(char* startOfLine);//生成rtsp发送命令;char * GetRTSPCmd(const char *);char * GetOptionCmd(char *url);char * GetDescribeCmd(char *url);char * GetPlayCmd(char *url, char *session, char *range);char * GetSetupCmd(char *url, int port1, int port2);char * GetReportCmd(char *);////////////////////////////////////////////////////////////////////////////日志函数;long logwr(void *, int len);//全局变量定义区;fd_set rfdsock;//日志写入文件指针;FILE *fp = NULL;//////////////////////////////////////////////////////////////////////////////rtsp请求解析;long PraseURL(const char *url, char *szip, int *iport);int _tmain(int argc, _TCHAR* argv[]){int sockin, sc1, sc2;sockaddr_in addr;char *buf, *szcmd, *url;char szip[32];int nlen, iret, iport;int ip1, ip2;long lret;//初始化变量;FD_ZERO(&rfdsock);fp = fopen("rtsp_log.txt", "w+");//分配缓冲区;nlen = 10240;buf = (char*)malloc(nlen);//定义要连接的url;//url = "rtsp://192.168.1.43:2554/realmp3.mp3";url = "rtsp://192.168.10.177/bipbop-gear1-all.ts";//url = "rtsp://192.168.1.43/1.amr";//初始化sock;InitSocket();//分析url请求,取出ip,端口;lret = PraseURL(url, szip, &iport);//初始化与服务器连接的socket;sockin = InitTCPSocket(0);//与服务器连接;addr.sin_family = AF_INET;addr.sin_port = htons(iport);addr.sin_addr.s_addr = inet_addr(szip);iret = connect(sockin,(struct sockaddr*)&addr, sizeof addr);if(iret   ==   SOCKET_ERROR)   {   int   erro   =   WSAGetLastError();   printf("connect   fail   !");Sleep(3000);     closesocket(sockin);   WSACleanup();     return 0;     } //发送option命令;szcmd = GetOptionCmd(url);lret = SendRTSPCmd(sockin, "OPTIONS",szcmd);free(szcmd);lret = ReadSocket(sockin, buf, nlen,100);//发送DESCRIBE命令;szcmd = GetDescribeCmd(url);lret = SendRTSPCmd(sockin, "DESCRIBE", szcmd);free(szcmd);lret = ReadSocket(sockin, buf,  nlen, 100);//解析Response;lret = PraseDescribeCmd((const char*)buf);//创建客户端接收端口;sc1 = InitUDPSocket(NULL, 6544);sc2 = InitUDPSocket(NULL, 6545);//将sock加入到要等待的队列;FD_SET(sc1, &rfdsock );FD_SET(sc2, &rfdsock);lret = GetSokcetPort(sc1, &ip1);lret = GetSokcetPort(sc2, &ip2);//发送Setup命令,告诉服务器客户端的接受数据的端口;szcmd = GetSetupCmd(url, ip1, ip2);//告诉服务器客户端的端口;lret = SendRTSPCmd(sockin, "SETUP", szcmd);free(szcmd);lret = ReadSocket(sockin, buf, nlen, 100);//解析Response返回的命令串;char szip2[9];lret = PraseSetupCmd(buf, szip2);char *session, *srange;session = szip2;//发送PLAY命令srange  = "Range: npt=0.000-39.471\r\n";szcmd = GetPlayCmd(url, session, srange);lret = SendRTSPCmd(sockin, "PLAY", szcmd);free(szcmd);lret = ReadSocket(sockin, buf, nlen, 100);timeval tv;fd_set fr;int i;tv.tv_sec = 20;tv.tv_usec = 0;struct sockaddr_in addr2;int addrlen;addrlen = sizeof addr;//将数据写到文件中去;FILE *ffp;ffp = fopen("bipbop-gear1-all.ts", "w+");//开始接受数据了;while(true){fr = rfdsock;lret  = select(0, &fr, NULL, NULL, &tv);if(lret == SOCKET_ERROR){break;}else if(lret >0){//判断是哪个socket可以读取数据了for(i = 0; i< 2;i ++){if(FD_ISSET(rfdsock.fd_array[i], &fr)&& FD_ISSET(rfdsock.fd_array[i], &rfdsock)){lret = recvfrom(rfdsock.fd_array[i], buf, nlen,0, (struct sockaddr*)&addr2, &addrlen );if(lret > 0 && ffp){fwrite(buf, 1, lret, ffp);}else if(lret == SOCKET_ERROR){break;}}}}else if(lret == 0)break;}fclose(ffp);//退出后的清理工作closesocket(sockin);closesocket(sc1);closesocket(sc2);fwrite("\r\nend", 1, 5, fp);fclose(fp);return 0;}long InitSocket(){WSADATA ws;long lret  = -1;lret = WSAStartup(MAKEWORD(2,2), &ws);return 0;}long DeInitSocket(){WSACleanup();return 0;}long InitTCPSocket( int port ){long lret ;int sock;sockaddr_in addr;sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//int flag = 1;//lret = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&flag, sizeof flag);//addr.sin_family = AF_INET;//addr.sin_port = 0;//addr.sin_addr.s_addr = INADDR_ANY;//lret = bind(sock, (struct sockaddr*)&addr, sizeof addr);lret = sock;return lret;}#define   SIO_RCVALL                         _WSAIOW(IOC_VENDOR,1)   #define   SIO_RCVALL_MCAST             _WSAIOW(IOC_VENDOR,2)   #define   SIO_RCVALL_IGMPMCAST     _WSAIOW(IOC_VENDOR,3)   #define   SIO_KEEPALIVE_VALS         _WSAIOW(IOC_VENDOR,4)   #define   SIO_ABSORB_RTRALERT       _WSAIOW(IOC_VENDOR,5)   #define   SIO_UCAST_IF                     _WSAIOW(IOC_VENDOR,6)   #define   SIO_LIMIT_BROADCASTS     _WSAIOW(IOC_VENDOR,7)   #define   SIO_INDEX_BIND                 _WSAIOW(IOC_VENDOR,8)   #define   SIO_INDEX_MCASTIF           _WSAIOW(IOC_VENDOR,9)   #define   SIO_INDEX_ADD_MCAST       _WSAIOW(IOC_VENDOR,10)   #define   SIO_INDEX_DEL_MCAST       _WSAIOW(IOC_VENDOR,11)   long InitUDPSocket(const char *ip,  int port ){long lret;int sock;sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);int flag = 1;lret = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&flag, sizeof flag);sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = port;if(ip)addr.sin_addr.s_addr = inet_addr(ip);elseaddr.sin_addr.s_addr = INADDR_ANY;lret = bind(sock, (struct sockaddr*)&addr, sizeof addr);//设置非堵塞通讯//u_long arg = 2; //lret = ioctlsocket(sock, SIO_LIMIT_BROADCASTS, &arg);lret = sock;return lret;}long GetSokcetPort( int sock, int *port ){long lret = -1;sockaddr_in addr;int nlen;nlen = sizeof addr;addr.sin_port = 0;*port = 0;if(getsockname(sock, (struct sockaddr*)&addr, &nlen) < 0)lret = -1;else{lret = 0;*port = addr.sin_port;}return lret;}long ReadSocket(int sock,  char *buf, int len, int timeout ){long lret ;int iret;fd_set fr;timeval tm;tm.tv_sec = timeout;tm.tv_usec = 0;FD_ZERO(&fr);fr.fd_count = 1;fr.fd_array[0] = sock;lret = select(sock, &fr, NULL, NULL, &tm);if(lret > 0){lret = recv(sock, buf, len, 0);if(lret == SOCKET_ERROR){}else if(lret > 0){logwr((void*)"***Recive:\r\n", 12);logwr((void*)buf, lret);}}return lret;}long SendRTSPCmd( int sock, const char *cmd, const char *szparam ){long lret;int ilen;ilen = strlen(szparam);lret = send(sock, szparam, ilen,0);if(lret == SOCKET_ERROR){lret = WSAGetLastError();}logwr((void*)"***Send:\r\n", 10);logwr((void *)szparam, ilen);return lret;}char * GetRTSPCmd( const char * szName){char *str = NULL;char const*  cmdFmt = NULL;if(!strcmp(szName, "OPTIONS")){cmdFmt ="OPTIONS %s RTSP/1.0\r\n""CSeq: %d\r\n""%s""%s"#ifdef SUPPORT_REAL_RTSPREAL_OPTIONS_HEADERS#endif"\r\n";}else if(!strcmp(szName, "ANNOUNCE")){cmdFmt ="ANNOUNCE %s RTSP/1.0\r\n""CSeq: %d\r\n""Content-Type: application/sdp\r\n""%s""Content-length: %d\r\n\r\n""%s";}else if(!strcmp(szName, "PLAY")){cmdFmt ="PLAY %s RTSP/1.0\r\n""CSeq: %d\r\n""Session: %s\r\n""%s""%s""%s""%s""\r\n";}else if(!strcmp(szName, "PAUSE")){cmdFmt ="PAUSE %s RTSP/1.0\r\n""CSeq: %d\r\n""Session: %s\r\n""%s""%s""\r\n";}else if(!strcmp(szName, "RECORD")){cmdFmt ="RECORD %s%s%s RTSP/1.0\r\n""CSeq: %d\r\n""Session: %s\r\n""Range: npt=0-\r\n""%s""%s""\r\n";}else if(!strcmp(szName, "SET_PARAMETER")){cmdFmt ="SET_PARAMETER %s RTSP/1.0\r\n""CSeq: %d\r\n""Session: %s\r\n""%s""%s""Content-length: %d\r\n\r\n""%s: %s\r\n";}else if(!strcmp(szName, "GET_PARAMETER")){cmdFmt ="GET_PARAMETER %s RTSP/1.0\r\n""CSeq: %d\r\n""Session: %s\r\n""%s""%s""Content-type: text/parameters\r\n""Content-length: %d\r\n\r\n""%s\r\n";}else if(!strcmp(szName, "TEARDOWN")){cmdFmt ="TEARDOWN %s RTSP/1.0\r\n""CSeq: %d\r\n""Session: %s\r\n""%s""%s""\r\n";}else if(!strcmp(szName, "DESCRIBE")){cmdFmt ="DESCRIBE %s RTSP/1.0\r\n""CSeq: %d\r\n""%s""%s""%s"#ifdef SUPPORT_REAL_RTSPREAL_DESCRIBE_HEADERS#endif"\r\n";}else if(!strcmp(szName, "ANNOUNCE")){cmdFmt ="ANNOUNCE %s RTSP/1.0\r\n""CSeq: %d\r\n""Content-Type: application/sdp\r\n""%s""Content-length: %d\r\n\r\n""%s";}else if(!strcmp(szName, "SETUP")){cmdFmt ="SETUP %s""CSeq: %d\r\n""%s""%s""%s""%s""\r\n";}str = (char*)cmdFmt;return str;}char * GetOptionCmd( char *url ){int nlen, iret;char *ss;char *s = GetRTSPCmd("OPTIONS");nlen = strlen(s);iret = nlen + strlen(url) + strlen(PP_NAME) + 200;ss = (char*)malloc(iret);sprintf(ss, s, url, 1, PP_NAME, PP_CRLF);return ss;}char * GetDescribeCmd( char *url ){int nlen, iret;char *ss;char *s = GetRTSPCmd("DESCRIBE");nlen = strlen(s);iret = nlen + strlen(url) + strlen(PP_NAME) + 200;ss = (char*)malloc(iret);sprintf(ss, s, url, 2, PP_NAME, PP_CRLF, PP_CRLF);return ss;}char * GetPlayCmd( char *url , char *session, char *range){int nlen, iret;char *ss;char *s = GetRTSPCmd("PLAY");nlen = strlen(s);iret = nlen + strlen(url) + strlen(PP_NAME) + 200;ss = (char*)malloc(iret);//char buf[128] = {0};//sprintf(buf, "Session: %s\r\n", session);sprintf(ss, s, url, 4, session, range, PP_NAME, PP_CRLF, PP_CRLF);return ss;}char * GetSetupCmd( char *url , int port1, int port2){int nlen, iret;char *ss;char *s = GetRTSPCmd("SETUP");nlen = strlen(s);iret = nlen + strlen(url) + strlen(PP_NAME) + 200;ss = (char*)malloc(iret);char buf[128] = {0};char buf2[128] = {0};if(port1 == 0)strcpy(buf, "\r\nTransport: RTP/AVP/TCP;unicast;interleaved=0-1");elsesprintf(buf, "\r\nTransport: RTP/AVP;unicast;client_port=%d-%d", ntohs(port2), ntohs(port1));//sprintf(buf2, "SETUP %s/streamid=0 RTSP/1.0\r\n", url);//sprintf(ss, s, buf2, 3,  buf, PP_NAME, PP_CRLF, PP_CRLF);sprintf(buf2, "%s/track1 RTSP/1.0\r\n", url);sprintf(ss, s, buf2, 3,  PP_NAME, buf, PP_CRLF, PP_CRLF);return ss;}long PraseURL( const char *url, char *szip, int *iport ){long lret = -1;if(url){ //找到了rtsp这个标识符if(!_strnicmp(url, "rtsp://", 7)){//找ipchar *s, *ss;s = (char*)url + strlen("rtsp://");ss = strchr(s, '/');strncpy(szip, s,  ss- s);szip[ss -s] = '\0';//查找下是否是有端口设置s = strchr(szip, ':');//有端口设置if(s){ss = s;s ++;*iport = atoi(s);//同时修正ip地址szip[ss - szip] = '/0';}else*iport = 554;lret = 0;}}return lret;}long logwr( void *data, int len ){long lret = -1;if(fp)lret = fwrite(data, 1, len, fp);return lret;}static char* getLine(char* startOfLine) {// returns the start of the next line, or NULL if nonefor (char* ptr = startOfLine; *ptr != '\0'; ++ptr) {// Check for the end of line: \r\n (but also accept \r or \n by itself):if (*ptr == '\r' || *ptr == '\n') {// We found the end of the lineif (*ptr == '\r') {*ptr++ = '\0';if (*ptr == '\n') ++ptr;} else {*ptr++ = '\0';}return ptr;}}return NULL;}long GetResponseCode( const char *sz ){long lret = -1;if(sz){if(sscanf(sz, "%*s%u", &lret) != 1);}return lret;}long PraseDescribeCmd( const char *sz ){long lret = -1;char *ss, *szst;szst = (char *)sz;int contentLength = -1;if(GetResponseCode(sz )== 200){ss= getLine(szst);while(1){ss = getLine(ss);if(ss == NULL)break;if (sscanf(ss, "Content-Length: %d", &contentLength) == 1|| sscanf(ss, "Content-length: %d", &contentLength) == 1) {if (contentLength < 0) {//....}}}}return lret;}long PraseSetupCmd( const char *sz , char *sess){long lret = -1;char *ss, *szst;szst = (char *)sz;int contentLength = -1;if(GetResponseCode(sz )== 200){ss= getLine(szst);while(1){ss = getLine(ss);if(ss == NULL)break;if (sscanf(ss, "Session: %sP4 192.168.10.177", sess) == 1){lret = 1;return lret;}}}return lret;}