iOS入门学什么?—— 先写个简单的Demo,比如做个视频直播吧(WebRTC)上

aaa.jpeg

惯例 ,WebRTC是什么####

就是 Web browsers with Real-Time Communications 啊
它是Google开源的啊,不要钱啊!

为什么要用WebRTC?####

就是老板叫看一下的啊
它是Google开源的啊,不要钱啊!

就是这样,不要在意太多细节 —— 百里潋長

目标####

在内网里使用iOS实现视频通话


有了目标就很容易知道需要些什么

服务器######

WebRTC使用libjingle进行穿透,p2p传输数据,连接过程为
尝试直连……
尝试使用Stun Service进行穿透……
尝试使用Turn Service进行中转……
这里只进行内网视频通话,就不需要准备Stun以及Turn服务器了。但即便如此,在交换通信的元数据(信令)的时候依然需要一个服务器,并且WebRTC并没有统一实现 —— 我们还需要简单地实现一个信令服务器来支持这个Demo。
我使用Java搭建信令服务器,WebSocket是一个用来做WebRTC信令的好方式,今后加上Web一起视频也是轻松加愉快

iOS######
  1. Safari显然还没有支持WebRTC的视频通话,只能使用代码来实现,在这里使用libjingle_peerconnection库(传送门)来实现WebRTC通话
  2. iOS上使用WebSocket有一个非常不错的轮子SocketRocket(传送门)
  3. 其他常用库AFNetworkingReactiveCocoaMantleSVProgressHUDMasonry

我们不生产代码,我们只是Github的搬运工 —— 农夫三拳,有点疼……


从信令服务开始####

JavaEE 7中出了JSR-356:Java API for WebSocket规范。我们需要使用JDK 7 以上版本,以Tomcat作为Web容器需要Tomcat 7.0.47 以上版本即可。
Java WebSocket只是跑起来不可谓不简单,我们新建一个Java Web项目名字就随便叫做VideoMeeting好了。再随便创建一个SocketAction类来完成信令转发,只需要简单地标注@ServerEndpoint (访问地址)@OnOpen (新建连接)@OnClose (断开连接)@OnMessage (接受到消息) 这几个注解就可以完成工作

package com.hsq.videomeeting.socketservice;

import java.lang.reflect.Method;

import javax.websocket.CloseReason;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/socket/{userId}")
public class SocketAction {
   private Session session;
   private int userId;

   @OnOpen
   public void onOpen(Session session, @PathParam(value="userId")int userId) {
       //注意 @ServerEndpoint 标注时声明了可以传入一个userId字段,此处再次声明并接收,作为用户及Session唯一标识
       this.userId = userId;
       this.session = session;
       //这是另一个随便写的处理类,将Session保存,必要时通过userid可以查找到并处理一些逻辑,此处省略,在OnMessage处有说明省了哪些逻辑的
       SocketService.addAction(this);
       System.out.println("打开连接:"+userId);
   }
   
   @OnClose
   public void onClose(CloseReason c) {
       SocketService.removeAction(this);
       System.out.println("关闭连接:"+userId);
   }
   
   @OnError
   public void onError(Throwable t) {
       
   }
   
   @SuppressWarnings("unchecked")
   @OnMessage
   public void onMessage(String message) {
       String decodeString = null;
       try {
           decodeString = new String(decodeBase64(message),"utf-8");
       } catch (Exception e) {
           e.printStackTrace();
       }
       System.out.println("消息 "+decodeString);
       //此处省略一点代码哟~
       //我传递的message是一个经过base64编码的JSON串,此处需要:
       //1、解析收到的message串,获取发送者id,接受者id以及消息主体内容
       //2、如果内容是offer/anwser/Candidate,则通过接受者id查找到其Session,使用send转发出去(offer什么的在后面客户端解释)
       //3、还有其他诸如接听、挂断、拒绝、正在通话中等等就自己脑洞啦
   }
   
   public boolean send(String jsonMessage){
       try {
           String base64JSON = encodeBase64(jsonMessage.getBytes("utf-8"));
           session.getBasicRemote().sendText(base64JSON);
           return true;
       } catch (Exception e) {
           e.printStackTrace();
           return false;
       }
   }
   
   /*** 
    * 编码
    */  
   @SuppressWarnings({ "rawtypes", "unchecked" })
   public static String encodeBase64(byte[] input) throws Exception {
       Class clazz=Class.forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");
       Method mainMethod= clazz.getMethod("encode", byte[].class);
       mainMethod.setAccessible(true);
        Object retObj=mainMethod.invoke(null, new Object[]{input});
        return (String)retObj;
   }  
   /*** 
    * 解码
    */  
   @SuppressWarnings({ "rawtypes", "unchecked" })
   public static byte[] decodeBase64(String input) throws Exception {
       Class clazz=Class.forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");
       Method mainMethod= clazz.getMethod("decode", String.class);
       mainMethod.setAccessible(true);
        Object retObj=mainMethod.invoke(null, input);
        return (byte[])retObj;
   }

   public Session getSession() {
       return session;
   }

   public int getUserId() {
       return userId;
   }

   public void setUserId(int userId) {
       this.userId = userId;
   }

   @Override
   public int hashCode() {
       final int prime = 31;
       int result = 1;
       result = prime * result + userId;
       return result;
   }
   
   @Override
   public boolean equals(Object obj) {
       if (this == obj)
           return true;
       if (obj == null)
           return false;
       if (getClass() != obj.getClass())
           return false;
       SocketAction other = (SocketAction) obj;
       if (userId != other.userId)
           return false;
       return true;
   }
}

我们把它发布到Tomcat中运行起来,在iOS中尝试使用SocketRocket进行连接

NSString * const WEBSOCKET_ADDRESS = @"ws://192.168.168.41:9999/VideoMeeting/socket/";
NSString *urlStr = [NSString stringWithFormat:@"%@%d", WEBSOCKET_ADDRESS,[User user].userId];
SRWebSocket  *socket = [[SRWebSocket alloc] initWithURL:[NSURL URLWithString:urlStr]];
socket.delegate = self;
[socket open];

这时就能在SRWebSocket的Delegate回调函数中获取到消息

////Delegate  -  WebSocket正常创建连接
- (void)webSocketDidOpen:(SRWebSocket *)webSocket {
    NSLog(@"连接到信令服务器啦");
}
////Delegate  -  接受消息的函数
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(NSString *)message {
    NSLog(@"接受到消息啦:%@",message);
}

有了信令服务器,不过还有关于用户体系和好友关系链之类的接口,不过不是视频必须并且与WebRTC无关,就不啰嗦了,接下来就开始着手敲iOS端的代码了啊喂

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容