打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
使用AsyncSocket实现RTSP协议

之前Socket一直使用Linux c来实现,优点是很容易掌握socket的通信流程,缺点是过程比较繁琐。

所以选择了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. #import "RTSPClient.h"

  9. #import "AsyncSocket.h"

  10. #import "AsyncUdpSocket.h"







  11. #define KENTER @"\r\n"

  12. #define KBLACK @" "

  13. #define MAX_BUF 10240





  14. static    NSString* SERVERADDR  = @"172.16.108.200";

  15. static  const  int  SERVERPORT = 554;





  16. @interface RTSPClient ()



  17. @end



  18. @implementation RTSPClient



  19. - (void)viewDidLoad

  20. {

  21.      [super viewDidLoad];

  22.      // Do any additional setup after loading the view, typically from a nib.

  23.      

  24.      

  25.      socket = [[AsyncSocket alloc] initWithDelegate:self];

  26.      

  27.      [socket connectToHost:@"172.16.108.200" onPort:554 error:nil];

  28.      [self getOptions];

  29.      

  30.       

  31. }



  32. - (void)viewDidUnload

  33. {

  34.      [super viewDidUnload];

  35.      // Release any retained subviews of the main view.

  36. }



  37. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

  38. {

  39.      return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);

  40. }













  41. #pragma mark RTSP Session

  42. /*

  43.   *建立连接,返回服务器对OPTIONS请求的响应

  44.   */

  45. -(NSMutableString*)getOptions

  46. {

  47.      

  48.      NSMutableString* options = [[NSMutableString alloc] init];

  49.      

  50.      [options appendFormat:@"OPTIONS rtsp://%@:%d/H264 RTSP/1.0%@",SERVERADDR,SERVERPORT,KENTER];

  51.      [options appendFormat:@"CSeq: 2%@",KENTER];

  52.      [options appendFormat:@"User-Agent: LibVLC/1.1.11 (LIVE555 Streaming Media v2011.05.25)%@%@",KENTER,KENTER];

  53.      

  54.      

  55.      [socket writeData:[options dataUsingEncoding:NSUTF8StringEncoding] withTimeout:3 tag:1];

  56.      NSMutableString* readString = [[NSMutableString alloc] init];

  57.      [socket readDataWithTimeout:3 tag:1];

  58.      

  59.      return readString;

  60. }



  61. /*

  62.   *建立连接,返回服务器对DESCRIBE请求的响应

  63.   */

  64. -(NSMutableString*)getDescribe

  65. {

  66.      

  67.      NSMutableString* describe = [[NSMutableString alloc] init];

  68.      

  69.      [describe appendFormat:@"DESCRIBE rtsp://%@:%d/H264 RTSP/1.0%@",SERVERADDR,SERVERPORT,KENTER];

  70.      [describe appendFormat:@"CSeq: 3%@",KENTER];

  71.      [describe appendFormat:@"Authorization: Basic YWRtaW4=%@",KENTER];

  72.      [describe appendFormat:@"User-Agent: LibVLC/1.1.11 (LIVE555 Streaming Media v2011.05.25)%@",KENTER];

  73.      [describe appendFormat:@"Accept: application/sdp%@%@",KENTER,KENTER];

  74.      

  75.      

  76.      

  77.      [socket writeData:[describe dataUsingEncoding:NSUTF8StringEncoding] withTimeout:3 tag:1];

  78.      NSMutableString* readString = [[NSMutableString alloc] init];

  79.      [socket readDataWithTimeout:3 tag:2];

  80.      

  81.      

  82.      return readString;

  83. }



  84. /*

  85.   *建立连接,返回通过tcp连接服务器对SETUP请求的响应

  86.   */

  87. -(NSMutableString*)getTcpSetup

  88. {

  89.      

  90.      

  91.      NSMutableString* tcpsetup = [[NSMutableString alloc] init];

  92.      

  93.      [tcpsetup appendFormat:@"SETUP rtsp://%@:%d/H264/track1 RTSP/1.0%@",SERVERADDR,SERVERPORT,KENTER];

  94.      [tcpsetup appendFormat:@"CSeq: 4%@",KENTER];

  95.      

  96.      [tcpsetup appendFormat:@"Authorization: Basic YWRtaW4=%@",KENTER];

  97.      [tcpsetup appendFormat:@"User-Agent: LibVLC/1.1.11 (LIVE555 Streaming Media v2011.05.25)%@",KENTER];

  98.      [tcpsetup appendFormat:@"Transport: RTP/AVP/TCP;unicast;interleaved=0-1%@%@",KENTER,KENTER];

  99.      

  100.      

  101.      

  102.      [socket writeData:[tcpsetup dataUsingEncoding:NSUTF8StringEncoding] withTimeout:3 tag:1];

  103.      NSMutableString* readString = [[NSMutableString alloc] init];

  104.      [socket readDataWithTimeout:3 tag:3];

  105.      

  106.      

  107.      return readString;

  108.      

  109. }



  110. /*

  111.   *建立连接,返回通过udp连接服务器对SETUP请求的响应

  112.   */

  113. -(NSMutableString*)getUdpSetup

  114. {

  115.      

  116.      NSMutableString* udpsetup = [[NSMutableString alloc] init];

  117.      

  118.      [udpsetup appendFormat:@"SETUP rtsp://%@/H264/track1 RTSP/1.0%@",SERVERADDR,KENTER];

  119.      [udpsetup appendFormat:@"CSeq: 4%@",KENTER];

  120.      [udpsetup appendFormat:@"Authorization: Basic YWRtaW4=%@",KENTER];

  121.      [udpsetup appendFormat:@"User-Agent: LibVLC/1.1.11 (LIVE555 Streaming Media v2011.05.25)%@",KENTER];

  122.      [udpsetup appendFormat:@"Transport: RTP/AVP;unicast;client_port=7777-7778%@%@",KENTER,KENTER];

  123.      

  124.      

  125.      

  126.      [socket writeData:[udpsetup dataUsingEncoding:NSUTF8StringEncoding] withTimeout:3 tag:1];

  127.      NSMutableString* readString = [[NSMutableString alloc] init];

  128.      [socket readDataWithTimeout:3 tag:3];   

  129.      

  130.      

  131.      return readString;

  132.      

  133. }



  134. /*

  135.   *建立连接,返回向服务器对PLAY请求的响应

  136.   */

  137. -(NSMutableString*)getPlay:(NSString*)session

  138. {

  139.      

  140.      NSMutableString* play = [[NSMutableString alloc] init];

  141.      

  142.      [play appendFormat:@"PLAY rtsp://%@/H264 RTSP/1.0%@",SERVERADDR,KENTER];

  143.      [play appendFormat:@"CSeq: 5%@",KENTER];

  144.      [play appendFormat:@"Range: npt=0.000-%@",KENTER];

  145.      [play appendFormat:@"Session:%@%@",session,KENTER];

  146.      [play appendFormat:@"User-Agent: LibVLC/1.1.11 (LIVE555 Streaming Media v2011.05.25)%@%@",KENTER,KENTER];

  147.      

  148.      

  149.      

  150.      [socket writeData:[play dataUsingEncoding:NSUTF8StringEncoding] withTimeout:3 tag:1];

  151.      NSMutableString* readString = [[NSMutableString alloc] init];

  152.      [socket readDataWithTimeout:3 tag:4];

  153.      

  154.      

  155.      return readString;

  156.      

  157. }







  158. /*

  159.   *建立连接,返回向服务器对TEARDOWN请求的响应

  160.   */

  161. -(NSMutableString*)getTeardown:(NSString*)session

  162. {

  163.      

  164.      NSMutableString* teardown = [[NSMutableString alloc] init];

  165.      

  166.      [teardown appendFormat:@"TEARDOWN rtsp://%@:%d/H264 RTSP/1.0%@",SERVERADDR,SERVERPORT,KENTER];

  167.      [teardown appendFormat:@"CSeq: 5%@",KENTER];

  168.      [teardown appendFormat:@"Session:%@%@",session,KENTER];

  169.      [teardown appendFormat:@"User-Agent: LibVLC/1.1.11 (LIVE555 Streaming Media v2011.05.25)%@%@",KENTER,KENTER];

  170.      

  171.      

  172.      [socket writeData:[teardown dataUsingEncoding:NSUTF8StringEncoding] withTimeout:3 tag:1];

  173.      NSMutableString* readString = [[NSMutableString alloc] init];

  174.      [socket readDataWithTimeout:3 tag:5];     

  175.      return readString;

  176.      

  177. }



  178. /*

  179.   *返回服务器地址

  180.   */

  181. -(NSString*)getServeraddr

  182. {

  183.      return SERVERADDR;

  184. }



  185. /*

  186.   *返回RTSP回话标识,info为客户端向服务器发送setup请求时的响应信息

  187.   */

  188. -(NSString*)getSession:(NSString*)info

  189. {

  190.      

  191.      //从文件中再一行一行读取数据,将包含session的一行保留出来

  192.      NSString *tmp;

  193.      NSArray *lines; /*将文件转化为一行一行的*/

  194.      lines = [info componentsSeparatedByString:@"\r\n"];

  195.      

  196.      NSEnumerator *nse = [lines objectEnumerator];

  197.      NSString* session = [[NSString alloc] init];

  198.      while(tmp = [nse nextObject]) {

  199.          if ([tmp hasPrefix:@"Session:"]) {

  200.              //tmp为包含session那一行的

  201.              NSInteger len = @"Session:".length;

  202.              session = [[tmp substringFromIndex:len] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

  203.              NSLog(@"Session:%@\n",session);   

  204.              break;

  205.          }

  206.      }

  207.      

  208.      return  session;

  209.      

  210. }



  211. /*

  212.   *返回RTSP回话的Content-Base

  213.   */

  214. -(NSString*)getContentBase:(NSString*)info

  215. {

  216.      //info为Describe请求所响应的信息

  217.      NSString *tmp;

  218.      NSArray *lines; /*将文件转化为一行一行的*/

  219.      lines = [info componentsSeparatedByString:@"\r\n"];

  220.      

  221.      NSEnumerator *nse = [lines objectEnumerator];

  222.      NSString* contentbase = [[NSString alloc] init];

  223.      while(tmp = [nse nextObject]) {

  224.          if ([tmp hasPrefix:@"Content-Base:"]) {

  225.              //tmp为包含session那一行的

  226.              NSInteger len = @"Content-Base:".length;

  227.              contentbase = [[info substringFromIndex:len] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

  228.              NSLog(@"Content-Base:%@\n",contentbase);   

  229.              break;

  230.          }

  231.      }

  232.      

  233.      return  contentbase;

  234.      

  235. }





  236. /*

  237.   *返回RTSP回话的Content-Type

  238.   */

  239. -(NSString*)getContentType:(NSString*)info

  240. {

  241.      

  242.      //info为Describe请求所响应的信息

  243.      NSString *tmp;

  244.      NSArray *lines; /*将文件转化为一行一行的*/

  245.      lines = [info componentsSeparatedByString:@"\r\n"];

  246.      

  247.      NSEnumerator *nse = [lines objectEnumerator];

  248.      NSString* contenttype = [[NSString alloc] init];

  249.      while(tmp = [nse nextObject]) {

  250.          if ([tmp hasPrefix:@"Content-Type:"]) {

  251.              //tmp为包含session那一行的

  252.              NSInteger len = @"Content-Type:".length;

  253.              contenttype = [[info substringFromIndex:len] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

  254.              NSLog(@"CContent-Type:%@\n",contenttype);   

  255.              break;

  256.          }

  257.      }

  258.      

  259.      return  contenttype;

  260.      

  261. }







  262. /*

  263.   *返回RTSP回话的contentlength

  264.   */

  265. -(NSString*)getContentLength:(NSString*)info

  266. {

  267.      

  268.      //info为Describe请求所响应的信息

  269.      NSString *tmp;

  270.      NSArray *lines; /*将文件转化为一行一行的*/

  271.      lines = [info componentsSeparatedByString:@"\r\n"];

  272.      

  273.      NSEnumerator *nse = [lines objectEnumerator];

  274.      NSString* contentlength = [[NSString alloc] init];

  275.      while(tmp = [nse nextObject]) {

  276.          if ([tmp hasPrefix:@"Content-Type:"]) {

  277.              //tmp为包含session那一行的

  278.              NSInteger len = @"Content-Type:".length;

  279.              contentlength = [[info substringFromIndex:len] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

  280.              NSLog(@"CContent-Type:%@\n",contentlength);   

  281.              break;

  282.          }

  283.      }

  284.      return  contentlength;   

  285. }



  286. /*

  287.   *本机作为客户端连接接受服务器发送的消息

  288.   */

  289. -(void)RecvUDPData{

  290.      

  291.      socketudp = [[AsyncUdpSocket alloc] initWithDelegate:self];

  292.    

  293.      [socketudp bindToPort:7777 error:nil];

  294.      [socketudp enableBroadcast:YES error:nil];//设置为广播

  295.      

  296.      if ([socketudp connectToHost:@"172.16.108.200" onPort:6970 error:nil]) {

  297.              [socketudp receiveWithTimeout:-1 tag:1];//将不断接受摄像头发送的数据

  298.      }

  299.          

  300. }



  301. #pragma mark AsyncSocketDelegate

  302. /*

  303.   *通过主机名和端口号连接服务器

  304.   */

  305. - (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port{

  306.      NSLog(@"did connect to host");

  307. }

  308. /*

  309.   *向内存中写入数据

  310.   */

  311. - (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{

  312.      NSString *message;

  313.      NSString* info = [[NSString alloc] init];

  314.      switch (tag) {

  315.          case 1:

  316.              NSLog(@"getOptions:did read data");

  317.              message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

  318.              NSLog(@"message is: \n%@",message);

  319.              [self getDescribe];

  320.              break;

  321.          case 2:

  322.              NSLog(@"getDescribe:did read data");

  323.              message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

  324.              NSLog(@"message is: \n%@",message);

  325.              info = [self getUdpSetup];

  326.              break;  

  327.          case 3:

  328.              NSLog(@"getUdpSetup:did read data");

  329.              message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

  330.              NSLog(@"message is: \n%@",message);

  331.              NSString* session = [self getSession:info];

  332.              [self getPlay:session];

  333.              break;

  334.          case 4:

  335.              NSLog(@"getPlay:did read data");

  336.              message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

  337.              NSLog(@"message is: \n%@",message);

  338.              [self RecvUDPData];

  339.              break;

  340.          case 5:

  341.              NSLog(@"getTeardown:did read data");

  342.              message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

  343.              NSLog(@"message is: \n%@",message);

  344.              break;

  345.          default:

  346.              break;

  347.      }

  348.      

  349.      

  350.      

  351. }









  352. #pragma mark AsyncUdpSocketDelegate

  353. - (BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port

  354. {

  355.      NSLog(@"333333333");

  356.      NSString *theLine=[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; //Convert the UDP data to an NSString

  357.      

  358.      NSLog(@"%@", theLine);

  359.      

  360.      [theLine release];

  361.      

  362.      [socketudp receiveWithTimeout:-1 tag:1];



  363.      

  364.      return YES;     

  365.      

  366. }





  367. @end复制代码
复制代码

建立UDP会话后,摄像头开始向客户端发送RTP数据包,多包构成一帧数据,然后进行解码显示。


链接地址;http://www.1000phone.net/thread-7784-1-5.html
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
iOS应用中使用AsyncSocket库处理Socket通信的用法讲解
IOS开发之CocoaAsyncSocket学习
rtp、rtcp、rtsp、rsvp协议详解
RTMP/RTP/RTSP/RTCP的区别
RTSP简介以及常用方法使用实例
RTP协议分析
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服