#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调试代码的更多相关文章

  1. Eclipse debug断点调试代码时出现source not found问题

    偶尔调试代码的时候会出现这种事情,之前并没有特别注意,今天稍微搜集一下相关资料: 1.跳转到的代码的确没有源码,下载源码后选择源码位置后便会正常显示源码. 2.源码和class文件不一致.即便勾选了a ...

  2. PHPStorm+Wamp+Xdebug+Windows7调试代码

    Wamp 集成环境 PHPStorm+Xdebug 调试代码 2013.04.16 花了两个小时时间终于 , 配置成功了 ! 我的开发环境如下 , 其它环境也可以参考我的配置 开发环境 : Windo ...

  3. [ActionScript&Flex] FlashBuilder编译条件之如何屏蔽调试代码

    下面讲一下在FlashBuilder中如何添加编译器参数使我们在发布的时候不编译调试代码: 首先设置编译参数 编译参数设置好后,代码我们可以这样写: public class ConditionalC ...

  4. 在Ubuntu中使用JDB调试代码

    在Ubuntu中使用JDB调试代码 了解JDB JDB是JDK安装的一部分,是基于文本和命令行的调试工具,JDB是可以免费获取且平台独立的,缺点是只有命令行格式. JDB基础命令 在方法中设置断点st ...

  5. PyCharm实现高效远程调试代码

      PyCharm实现高效远程调试代码   (薛刚强)    为方便Python代码学习和项目开发,目前选择专业的 IDE 开发工具 ,如 PyCham.针对个人使用的技巧做个笔记,分享给大家,有描述 ...

  6. C++雾中风景番外篇3:GDB与Valgrind ,调试代码内存的工具

    写 C++的同学想必有太多和内存打交道的血泪经验了,常常被 C++的内存问题搅的焦头烂额.(写 core 的经验了)有很多同学一见到 core 就两眼一抹黑,不知所措了.笔者 入"坑&quo ...

  7. chrome单步调试代码

    单步调试代码 所有步骤选项均通过边栏中的可点击图标 表示,但也可以通过快捷键触发(鼠标悬停在操作图标上就可以看到快捷键).下面是简要介绍: 图标/按钮 操作 描述 Resume 继续执行直到下一个断点 ...

  8. JAVA Debug 调试代码

    JAVA Debug 调试代码 1.什么时候使用Debug: 程序的运行结果,与你的预期结果不同时,Debug的目的是找错误,而不是该错误: 2.早期调试代码的方式就是打桩: System.out.p ...

  9. vs2008 怎么在Release下调试代码

    vs2008 怎么在Release下调试代码 (适用VS2005/VS2008) 在当前工程点击右键选择properties,选择 All Configurations C++>General- ...

随机推荐

  1. git从github下载代码

    Github作为远程仓库的使用详解  http://blog.csdn.net/djl4104804/article/details/50778717 centos local:        通过g ...

  2. [条款36]绝不重新定义继承而来的non-virtual函数

    看下面的两个类的声明代码: class B { public: void mf(); //something to do }; class D : public B { public: void mf ...

  3. 使用 Async 和 Await 的异步编程 #Reprinted#

    异步方法容易编写 string urlContents = await client.GetStringAsync(); 以下特征总结了使上面一个异步方法. 方法签名包含一个 Async 或async ...

  4. Qt在各平台上的搭建qt-everywhere

    Qt for windows7-64bit 在电脑上安装mingw(搜索mingw for windows),将C:\MinGW\bin添加进环境变量,打开命令行输入gcc --version和g++ ...

  5. 解题报告 HDU1944 S-Nim

    S-Nim Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Problem De ...

  6. C# RSA在服务上使用出现拒绝方法错误的解决方法

    在做一个快钱接口的时候,遇到了.net RSA加密无法在一台win2008服务器上运行正常,更换到Win2003服务器后出现问题,具体表现如下: “/”应用程序中的服务器错误. ----------- ...

  7. 编程算法 - 最长公共子序列(LCS) 代码(C)

    最长公共子序列(LCS) 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 给定两个字符串s,t, 求出这两个字符串最长的公共子序列的长度. 字符 ...

  8. 为joomla加入�下拉菜单的方法

    用 Joomla! 建站的大多数站长都须要在站点前台使用下拉菜单(dropdown menu),或者叫弹出菜单(slide menu),由于这样能够在有限的页面空间上公布很多其它的导航菜单,而且能够进 ...

  9. Unity的Cover flow的实现包(2个)

    苹果的mac机上预览图片,有一个所谓的cover flow的效果,这里收集到两个,两个实现效果略有不同. 1.老外的实现 https://github.com/rakkarage/Unity3D-Co ...

  10. ThinkPHP - 前置操作+后置操作

    前置操作和后置操作   系统会检测当前操作(不仅仅是index操作,其他操作一样可以使用)是否具有前置和后置操作,如果存在就会按照顺序执行,前置和后置操作的方法名是在要执行的方法前面加 _before ...