iOS 使用AsyncSocket实现RTSP协议

所以选择了AsyncSocket来实现socket通信。另外实现了RTSP的通信过程,并在play命令之后,

再次开始一个UDP会话,用于传输数据。

  项目原型是用RTSP+RTP来实现摄像头的实时监控,RTSP使用TCP来实现,RTP使用UDP实现,

直接上代码吧!

关于怎么在项目中使用AysncSocket,请查看http://www.1000phone.net/thread-7781-1-1.htmlRTSPClient.h如下:

  1. //
  2. //  ViewController.m
  3. //  RTSPClient
  4. //
  5. //  Created by Fox on 12-3-11.
  6. //  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
  7. //
  8.  
  9. #import "RTSPClient.h"
  10. #import "AsyncSocket.h"
  11. #import "AsyncUdpSocket.h"
  12.  
  13.  
  14.  
  15. #define KENTER @"\r\n"
  16. #define KBLACK @" "
  17. #define MAX_BUF 10240
  18.  
  19.  
  20. static    NSString* SERVERADDR  = @"172.16.108.200";
  21. static  const  int  SERVERPORT = 554;
  22.  
  23.  
  24. @interface RTSPClient ()
  25.  
  26. @end
  27.  
  28. @implementation RTSPClient
  29.  
  30. - (void)viewDidLoad
  31. {
  32.      [super viewDidLoad];
  33.      // Do any additional setup after loading the view, typically from a nib.
  34.      
  35.      
  36.      socket = [[AsyncSocket alloc] initWithDelegate:self];
  37.      
  38.      [socket connectToHost:@"172.16.108.200" onPort:554 error:nil];
  39.      [self getOptions];
  40.      
  41.       
  42. }
  43.  
  44. - (void)viewDidUnload
  45. {
  46.      [super viewDidUnload];
  47.      // Release any retained subviews of the main view.
  48. }
  49.  
  50. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
  51. {
  52.      return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
  53. }
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60. #pragma mark RTSP Session
  61. /*
  62.   *建立连接,返回服务器对OPTIONS请求的响应
  63.   */
  64. -(NSMutableString*)getOptions
  65. {
  66.      
  67.      NSMutableString* options = [[NSMutableString alloc] init];
  68.      
  69.      [options appendFormat:@"OPTIONS rtsp://%@:%d/H264 RTSP/1.0%@",SERVERADDR,SERVERPORT,KENTER];
  70.      [options appendFormat:@"CSeq: 2%@",KENTER];
  71.      [options appendFormat:@"User-Agent: LibVLC/1.1.11 (LIVE555 Streaming Media v2011.05.25)%@%@",KENTER,KENTER];
  72.      
  73.      
  74.      [socket writeData:[options dataUsingEncoding:NSUTF8StringEncoding] withTimeout:3 tag:1];
  75.      NSMutableString* readString = [[NSMutableString alloc] init];
  76.      [socket readDataWithTimeout:3 tag:1];
  77.      
  78.      return readString;
  79. }
  80.  
  81. /*
  82.   *建立连接,返回服务器对DESCRIBE请求的响应
  83.   */
  84. -(NSMutableString*)getDescribe
  85. {
  86.      
  87.      NSMutableString* describe = [[NSMutableString alloc] init];
  88.      
  89.      [describe appendFormat:@"DESCRIBE rtsp://%@:%d/H264 RTSP/1.0%@",SERVERADDR,SERVERPORT,KENTER];
  90.      [describe appendFormat:@"CSeq: 3%@",KENTER];
  91.      [describe appendFormat:@"Authorization: Basic YWRtaW4=%@",KENTER];
  92.      [describe appendFormat:@"User-Agent: LibVLC/1.1.11 (LIVE555 Streaming Media v2011.05.25)%@",KENTER];
  93.      [describe appendFormat:@"Accept: application/sdp%@%@",KENTER,KENTER];
  94.      
  95.      
  96.      
  97.      [socket writeData:[describe dataUsingEncoding:NSUTF8StringEncoding] withTimeout:3 tag:1];
  98.      NSMutableString* readString = [[NSMutableString alloc] init];
  99.      [socket readDataWithTimeout:3 tag:2];
  100.      
  101.      
  102.      return readString;
  103. }
  104.  
  105. /*
  106.   *建立连接,返回通过tcp连接服务器对SETUP请求的响应
  107.   */
  108. -(NSMutableString*)getTcpSetup
  109. {
  110.      
  111.      
  112.      NSMutableString* tcpsetup = [[NSMutableString alloc] init];
  113.      
  114.      [tcpsetup appendFormat:@"SETUP rtsp://%@:%d/H264/track1 RTSP/1.0%@",SERVERADDR,SERVERPORT,KENTER];
  115.      [tcpsetup appendFormat:@"CSeq: 4%@",KENTER];
  116.      
  117.      [tcpsetup appendFormat:@"Authorization: Basic YWRtaW4=%@",KENTER];
  118.      [tcpsetup appendFormat:@"User-Agent: LibVLC/1.1.11 (LIVE555 Streaming Media v2011.05.25)%@",KENTER];
  119.      [tcpsetup appendFormat:@"Transport: RTP/AVP/TCP;unicast;interleaved=0-1%@%@",KENTER,KENTER];
  120.      
  121.      
  122.      
  123.      [socket writeData:[tcpsetup dataUsingEncoding:NSUTF8StringEncoding] withTimeout:3 tag:1];
  124.      NSMutableString* readString = [[NSMutableString alloc] init];
  125.      [socket readDataWithTimeout:3 tag:3];
  126.      
  127.      
  128.      return readString;
  129.      
  130. }
  131.  
  132. /*
  133.   *建立连接,返回通过udp连接服务器对SETUP请求的响应
  134.   */
  135. -(NSMutableString*)getUdpSetup
  136. {
  137.      
  138.      NSMutableString* udpsetup = [[NSMutableString alloc] init];
  139.      
  140.      [udpsetup appendFormat:@"SETUP rtsp://%@/H264/track1 RTSP/1.0%@",SERVERADDR,KENTER];
  141.      [udpsetup appendFormat:@"CSeq: 4%@",KENTER];
  142.      [udpsetup appendFormat:@"Authorization: Basic YWRtaW4=%@",KENTER];
  143.      [udpsetup appendFormat:@"User-Agent: LibVLC/1.1.11 (LIVE555 Streaming Media v2011.05.25)%@",KENTER];
  144.      [udpsetup appendFormat:@"Transport: RTP/AVP;unicast;client_port=7777-7778%@%@",KENTER,KENTER];
  145.      
  146.      
  147.      
  148.      [socket writeData:[udpsetup dataUsingEncoding:NSUTF8StringEncoding] withTimeout:3 tag:1];
  149.      NSMutableString* readString = [[NSMutableString alloc] init];
  150.      [socket readDataWithTimeout:3 tag:3];    
  151.      
  152.      
  153.      return readString;
  154.      
  155. }
  156.  
  157. /*
  158.   *建立连接,返回向服务器对PLAY请求的响应
  159.   */
  160. -(NSMutableString*)getPlay:(NSString*)session
  161. {
  162.      
  163.      NSMutableString* play = [[NSMutableString alloc] init];
  164.      
  165.      [play appendFormat:@"PLAY rtsp://%@/H264 RTSP/1.0%@",SERVERADDR,KENTER];
  166.      [play appendFormat:@"CSeq: 5%@",KENTER];
  167.      [play appendFormat:@"Range: npt=0.000-%@",KENTER];
  168.      [play appendFormat:@"Session:%@%@",session,KENTER];
  169.      [play appendFormat:@"User-Agent: LibVLC/1.1.11 (LIVE555 Streaming Media v2011.05.25)%@%@",KENTER,KENTER];
  170.      
  171.      
  172.      
  173.      [socket writeData:[play dataUsingEncoding:NSUTF8StringEncoding] withTimeout:3 tag:1];
  174.      NSMutableString* readString = [[NSMutableString alloc] init];
  175.      [socket readDataWithTimeout:3 tag:4]; 
  176.      
  177.      
  178.      return readString;
  179.      
  180. }
  181.  
  182.  
  183.  
  184. /*
  185.   *建立连接,返回向服务器对TEARDOWN请求的响应
  186.   */
  187. -(NSMutableString*)getTeardown:(NSString*)session
  188. {
  189.      
  190.      NSMutableString* teardown = [[NSMutableString alloc] init];
  191.      
  192.      [teardown appendFormat:@"TEARDOWN rtsp://%@:%d/H264 RTSP/1.0%@",SERVERADDR,SERVERPORT,KENTER];
  193.      [teardown appendFormat:@"CSeq: 5%@",KENTER];
  194.      [teardown appendFormat:@"Session:%@%@",session,KENTER];
  195.      [teardown appendFormat:@"User-Agent: LibVLC/1.1.11 (LIVE555 Streaming Media v2011.05.25)%@%@",KENTER,KENTER];
  196.      
  197.      
  198.      [socket writeData:[teardown dataUsingEncoding:NSUTF8StringEncoding] withTimeout:3 tag:1];
  199.      NSMutableString* readString = [[NSMutableString alloc] init];
  200.      [socket readDataWithTimeout:3 tag:5];     
  201.      return readString;
  202.      
  203. }
  204.  
  205. /*
  206.   *返回服务器地址
  207.   */
  208. -(NSString*)getServeraddr
  209. {
  210.      return SERVERADDR;
  211. }
  212.  
  213. /*
  214.   *返回RTSP回话标识,info为客户端向服务器发送setup请求时的响应信息
  215.   */
  216. -(NSString*)getSession:(NSString*)info
  217. {
  218.      
  219.      //从文件中再一行一行读取数据,将包含session的一行保留出来
  220.      NSString *tmp; 
  221.      NSArray *lines; /*将文件转化为一行一行的*/ 
  222.      lines = [info componentsSeparatedByString:@"\r\n"];
  223.      
  224.      NSEnumerator *nse = [lines objectEnumerator]; 
  225.      NSString* session = [[NSString alloc] init];
  226.      while(tmp = [nse nextObject]) { 
  227.          if ([tmp hasPrefix:@"Session:"]) {
  228.              //tmp为包含session那一行的
  229.              NSInteger len = @"Session:".length;
  230.              session = [[tmp substringFromIndex:len] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
  231.              NSLog(@"Session:%@\n",session);   
  232.              break;
  233.          }
  234.      }
  235.      
  236.      return  session;
  237.      
  238. }
  239.  
  240. /*
  241.   *返回RTSP回话的Content-Base
  242.   */
  243. -(NSString*)getContentBase:(NSString*)info
  244. {
  245.      //info为Describe请求所响应的信息
  246.      NSString *tmp; 
  247.      NSArray *lines; /*将文件转化为一行一行的*/ 
  248.      lines = [info componentsSeparatedByString:@"\r\n"];
  249.      
  250.      NSEnumerator *nse = [lines objectEnumerator]; 
  251.      NSString* contentbase = [[NSString alloc] init];
  252.      while(tmp = [nse nextObject]) { 
  253.          if ([tmp hasPrefix:@"Content-Base:"]) {
  254.              //tmp为包含session那一行的
  255.              NSInteger len = @"Content-Base:".length;
  256.              contentbase = [[info substringFromIndex:len] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
  257.              NSLog(@"Content-Base:%@\n",contentbase);   
  258.              break;
  259.          }
  260.      }
  261.      
  262.      return  contentbase;
  263.      
  264. }
  265.  
  266.  
  267. /*
  268.   *返回RTSP回话的Content-Type
  269.   */
  270. -(NSString*)getContentType:(NSString*)info
  271. {
  272.      
  273.      //info为Describe请求所响应的信息
  274.      NSString *tmp; 
  275.      NSArray *lines; /*将文件转化为一行一行的*/ 
  276.      lines = [info componentsSeparatedByString:@"\r\n"];
  277.      
  278.      NSEnumerator *nse = [lines objectEnumerator]; 
  279.      NSString* contenttype = [[NSString alloc] init];
  280.      while(tmp = [nse nextObject]) { 
  281.          if ([tmp hasPrefix:@"Content-Type:"]) {
  282.              //tmp为包含session那一行的
  283.              NSInteger len = @"Content-Type:".length;
  284.              contenttype = [[info substringFromIndex:len] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
  285.              NSLog(@"CContent-Type:%@\n",contenttype);   
  286.              break;
  287.          }
  288.      }
  289.      
  290.      return  contenttype;
  291.      
  292. }
  293.  
  294.  
  295.  
  296. /*
  297.   *返回RTSP回话的contentlength
  298.   */
  299. -(NSString*)getContentLength:(NSString*)info
  300. {
  301.      
  302.      //info为Describe请求所响应的信息
  303.      NSString *tmp; 
  304.      NSArray *lines; /*将文件转化为一行一行的*/ 
  305.      lines = [info componentsSeparatedByString:@"\r\n"];
  306.      
  307.      NSEnumerator *nse = [lines objectEnumerator]; 
  308.      NSString* contentlength = [[NSString alloc] init];
  309.      while(tmp = [nse nextObject]) { 
  310.          if ([tmp hasPrefix:@"Content-Type:"]) {
  311.              //tmp为包含session那一行的
  312.              NSInteger len = @"Content-Type:".length;
  313.              contentlength = [[info substringFromIndex:len] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
  314.              NSLog(@"CContent-Type:%@\n",contentlength);   
  315.              break;
  316.          }
  317.      }
  318.      return  contentlength;    
  319. }
  320.  
  321. /*
  322.   *本机作为客户端连接接受服务器发送的消息
  323.   */
  324. -(void)RecvUDPData{
  325.      
  326.      socketudp = [[AsyncUdpSocket alloc] initWithDelegate:self];
  327.     
  328.      [socketudp bindToPort:7777 error:nil];
  329.      [socketudp enableBroadcast:YES error:nil];//设置为广播
  330.      
  331.      if ([socketudp connectToHost:@"172.16.108.200" onPort:6970 error:nil]) {
  332.              [socketudp receiveWithTimeout:-1 tag:1];//将不断接受摄像头发送的数据
  333.      }
  334.           
  335. }
  336.  
  337. #pragma mark AsyncSocketDelegate
  338. /*
  339.   *通过主机名和端口号连接服务器
  340.   */
  341. - (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port{
  342.      NSLog(@"did connect to host");
  343. }
  344. /*
  345.   *向内存中写入数据
  346.   */
  347. - (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
  348.      NSString *message;
  349.      NSString* info = [[NSString alloc] init];
  350.      switch (tag) {
  351.          case 1:
  352.              NSLog(@"getOptions:did read data");
  353.              message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  354.              NSLog(@"message is: \n%@",message);
  355.              [self getDescribe];
  356.              break;
  357.          case 2:
  358.              NSLog(@"getDescribe:did read data");
  359.              message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  360.              NSLog(@"message is: \n%@",message);
  361.              info = [self getUdpSetup];
  362.              break;  
  363.          case 3:
  364.              NSLog(@"getUdpSetup:did read data");
  365.              message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  366.              NSLog(@"message is: \n%@",message);
  367.              NSString* session = [self getSession:info];
  368.              [self getPlay:session];
  369.              break; 
  370.          case 4:
  371.              NSLog(@"getPlay:did read data");
  372.              message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  373.              NSLog(@"message is: \n%@",message);
  374.              [self RecvUDPData];
  375.              break; 
  376.          case 5:
  377.              NSLog(@"getTeardown:did read data");
  378.              message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  379.              NSLog(@"message is: \n%@",message);
  380.              break; 
  381.          default:
  382.              break;
  383.      }
  384.      
  385.      
  386.      
  387. }
  388.  
  389.  
  390.  
  391.  
  392. #pragma mark AsyncUdpSocketDelegate
  393. - (BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port
  394. {
  395.      NSLog(@"333333333");
  396.      NSString *theLine=[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; //Convert the UDP data to an NSString
  397.      
  398.      NSLog(@"%@", theLine);
  399.      
  400.      [theLine release];
  401.      
  402.      [socketudp receiveWithTimeout:-1 tag:1]; 
  403.  
  404.      
  405.      return YES;     
  406.      
  407. }
  408.  
  409.  
  410. @end
复制代码
建立UDP会话后,摄像头开始向客户端发送RTP数据包,多包构成一帧数据,然后进行解码显示。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值