iOS + node.js使用Socket.IO框架进行实时通信

Socket.IO是一个基于WebSocket的实时通信库,在主流平台都有很好的支持,此文主要是通过一个小例子来演示Socket.IO的使用。

基础环境搭建

新建一个文件夹(JS工程),创建一个package.json,复制以下内容并保存。

{
  "name": "socket-chat-example",
  "version": "0.0.1",
  "description": "my first socket.io app",
  "dependencies": {}
}

然后执行npm命令,安装我们需要的依赖(Express和Socket.IO), 请确保你电脑已经有node环境

在项目根目录也就是package.json所在的目录在终端执行以下命令

npm install --save express@4.10.2

npm install --save socket.io

进度条读完后会多这么一个文件夹,此时Express和Socket.IO就已经安装好了,这和iOS的Cocopods差不多,以模块化进行加载。

node_modules

然后新建一个index.js作为服务端,再建一个index.html作为客户端。(为了方便演示,我这里有两个客户端,一个是iOS端,一个是浏览器端)

index.html

这也是官方Demo的演示界面,UI上没做修改

index.html

代码如下

<!doctype html>
<html>
  <head>
    <title>Socket.IO chat</title>
    <style>
      * { margin: 0; padding: 0; box-sizing: border-box; }
      body { font: 13px Helvetica, Arial; }
      form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
      form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
      form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
      #messages { list-style-type: none; margin: 0; padding: 0; }
      #messages li { padding: 5px 10px; }
      #messages li:nth-child(odd) { background: #eee; }
    </style>
  </head>
  <body>
    <ul id="messages"></ul>
    <form action="">
      <input id="m" autocomplete="off" /><button>Send</button>
    </form>
  </body>
</html>

index.js

var app = require('express')();
var http = require('http').Server(app);
var io   = require('socket.io')(http);

app.get('/',function(req,res){
    res.sendfile(__dirname + '/index.html');
});
http.listen(3000,function () {
    console.log('listien 3000');
});

开启了一个Server,监听3000端口,然后回到项目根目录,在终端输入
node index.js
如果出现listen 3000则表明服务开启成功了,此时在浏览器访问
http://localhost:3000 就能看到index.html页面了

iOS客户端的集成

新建一个iOS工程,在终端cd到项目根目录创建一个Podfile文件

vim Podfile

复制以下内容

use_frameworks!

target 'SocketIO_Chat_Example' do #项目名
    pod 'Socket.IO-Client-Swift', '~> 8.2.0'
end

保存退出,执行命令安装依赖

pod install or pod install --verbose --no-repo-update

请确保已经有cocopods环境

iOS端的UI

iOS

使用Socket.IO

此时我们的客户端和服务端都已经有了Socket.IO的环境了,接下来就是使用它进行聊天了。

Socket.IO中事件的处理主要通过这两个方法来实现的

on(_ event: String, callback: NormalCallback)

emit(_ event: String, _ items: AnyObject...)

on方法为接收事件的方法,emit为发送事件的方法

我们的需求是让浏览器和iOS客户端进行单聊

服务端的处理

要想发送到指定的客户端,需要知道当前客户端的id(Socket.IO的id,例:3t60BArlK47a2fA-AAAd),但是客户端并不清楚,客户端只知道我们自己定义的id,所以我们要将Socket.IO的Id和我们自己定义的id绑定并存储起来。

var socketArray = new Array();

io.on('connection', function(socket){
    var islogin = false;
    console.log('**********新加入了一个用户*********',socket.id);
    socket.on('login',function (userId) {
       if(islogin) return;
        socket.userId = userId;
        socketArray.push(socket);
       islogin = true;

    });
    socket.on('privateMessage',function (data) {
        console.log(data);
    })
    socket.on('chat message', function(data){
        var to   = data.toUser;
        var message = data.message;
        for(var i = 0;i<socketArray.length;i++){
            var receiveData = socketArray[i];
            if (receiveData.userId == to){
                io.to([receiveData.id]).emit('privateMessage',''+receiveData.userId+':'+message);
            }
        }
    });
    socket.on('disconnect',function () {
        console.log('***********用户退出登陆************,'+socket.id);
    })
});

客户端的处理

浏览器的处理

<script src="/socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
    var socket = io();
    socket.emit('login','30621');
    $('form').submit(function(){
        socket.emit('chat message',{'toUser':'30342','message':$('#m').val()} );
        $('#m').val('');
        return false;
    });
    socket.on('chat message', function(msg){
        $('#messages').append($('<li>').text(msg));
    });
    socket.on('privateMessage',function (msg) {
        $('#messages').append($('<li>').text(msg));
    });
</script>

iOS端的处理

iOS在初始化的时候需要一个config字典,config可以配置诸如log日志输出等设置

- (SocketIOClient *)client{
    if (!_client) {
        NSURL* url = [[NSURL alloc] initWithString:@"http://localhost:3000"];
        _client = [[SocketIOClient alloc] initWithSocketURL:url config:@{@"log": @YES, @"forcePolling": @YES}];
        
    }
    return _client;
}

- (void)connection{

    [self.client on:@"connect" callback:^(NSArray* data, SocketAckEmitter* ack) {
        NSLog(@"*************\n\niOS客户端上线\n\n*************");
        [self.client emit:@"login" with:@[@"30342"]];
    }];
    [self.client on:@"chat message" callback:^(NSArray * _Nonnull event, SocketAckEmitter * _Nonnull ack) {
        if (event[0] && ![event[0] isEqualToString:@""]) {
            [self.messageArray insertObject:event[0] atIndex:0];
            [self.messageTableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationTop];
        }
    }];
    [self.client on:@"privateMessage" callback:^(NSArray * _Nonnull event, SocketAckEmitter * _Nonnull ack) {
        if (event[0] && ![event[0] isEqualToString:@""]) {
            [self.messageArray insertObject:event[0] atIndex:0];
            [self.messageTableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationTop];
        }
    }];
    [self.client on:@"disconnect" callback:^(NSArray * _Nonnull event, SocketAckEmitter * _Nonnull ack) {
        NSLog(@"*************\n\niOS客户端下线\n\n*************%@",event?event[0]:@"");
    }];
    [self.client on:@"error" callback:^(NSArray * _Nonnull event, SocketAckEmitter * _Nonnull ack) {
        NSLog(@"*************\n\n%@\n\n*************",event?event[0]:@"");
    }];
    [self.client connect];

}
//按钮点击事件
- (IBAction)sendMessage:(id)sender {
    if (self.inputView.text.length>0) {
        
        [self.client emit:@"chat message" with:@[@{@"toUser":@"30621",@"message":self.inputView.text}]];
        [self.messageArray insertObject:self.inputView.text atIndex:0];
        [self.messageTableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationTop];
        self.inputView.text = @"";
    }
    
}

github地址

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

推荐阅读更多精彩内容

  • Web领域的实时推送技术,也被称作Realtime技术。这种技术要达到的目的是让用户不需要刷新浏览器就可以获得实时...
    潘良虎阅读 44,563评论 6 78
  • 个人入门学习用笔记、不过多作为参考依据。如有错误欢迎斧正 目录 简书好像不支持锚点、复制搜索(反正也是写给我自己看...
    kirito_song阅读 2,458评论 1 37
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,799评论 25 707
  • 亲爱的微马家人们你们知道毒品吗?你们知道毒品的危害吗?因为毒品这一白色瘟疫已蔓延全球,成为当今世界一大公害,各国政...
    若惜_57f9阅读 361评论 0 0
  • 我想写下一些东西,趁我还记得的时候。 每次看《千与千寻》都会哭,就是会莫名其妙的感动,我也不知道要哭的点在...
    野生妹妹啊阅读 1,301评论 0 1