RTSP调试代码

#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);
	else
		addr.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_RTSP
			REAL_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_RTSP
			REAL_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");
	else
		sprintf(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))
		{
			//找ip
			char *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 none
	for (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 line
			if (*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;
}


你可能感兴趣的:(RTSP调试代码)