#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_IN补充:软件开发 , C++ ,