500px技术周报002

socket.io

基于websocket实现客户端和服务器实时通讯,服务器采用的是node.js ,客户端支持java、c++、swift

服务器搭建

第一步检查当前环境是否安装了node.js

node -v 

npm -v  

如果没有, 下载mac版node.js并安装。

然后新建一个文件夹,在里面执行vim package.json输入一下内容

{
  "name": "realtime-server",
  "version": "0.0.1",
  "description": "my first realtime server",
  "dependencies": {}
}

然后执行

npm install --save express
npm install --save socket.io

然后执行vim index.js

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

app.get('/', function(req, res){
    res.send('<h1>Welcome Realtime Server</h1>');
});

//在线用户
var onlineUsers = {};
//当前在线人数
var onlineCount = 0;

io.on('connection', function(socket){
    console.log('a user connected');

    //监听新用户加入
    socket.on('login', function(obj){
        //将新加入用户的唯一标识当作socket的名称,后面退出的时候会用到
        socket.name = obj.userid;

        //检查在线列表,如果不在里面就加入
        if(!onlineUsers.hasOwnProperty(obj.userid)) {
            onlineUsers[obj.userid] = obj.username;
            //在线人数+1
            onlineCount++;
        }

        //向所有客户端广播用户加入
        io.emit('login', {onlineUsers:onlineUsers, onlineCount:onlineCount, user:obj});
        console.log(obj.username+'加入了聊天室');
    });

    //监听用户退出
    socket.on('disconnect', function(){
        //将退出的用户从在线列表中删除
        if(onlineUsers.hasOwnProperty(socket.name)) {
            //退出用户的信息
            var obj = {userid:socket.name, username:onlineUsers[socket.name]};

            //删除
            delete onlineUsers[socket.name];
            //在线人数-1
            onlineCount--;

            //向所有客户端广播用户退出
            io.emit('logout', {onlineUsers:onlineUsers, onlineCount:onlineCount, user:obj});
            console.log(obj.username+'退出了聊天室');
        }
    });

    //监听用户发布聊天内容
    socket.on('message', function(obj){
        //向所有客户端广播发布的消息
        io.emit('message', obj);
        console.log(obj.username+'说:'+obj.content);
    });

});

http.listen(3000, function(){
    console.log('listening on *:3000');
});

启动服务器 执行

node index.js

停止服务器使用control+C

客户端

CocoaPods方式集成

由于v10.0.0版本更新,doubleEncodeUTF8 已经被弃用,如果服务器使用的是老版本,客户端使用最新的代码,则会出现中文乱码情况。建议使用之前的版本,下面的例子中通过commit号来指定使用哪个版本。

Podfile里的内容如下:

platform :ios, '9.0'
use_frameworks!

target 'test' do
    pod 'Socket.IO-Client-Swift' ,:git => 'https://github.com/socketio/socket.io-client-swift.git',:commit => '1949b1fd487abb4301f57c608645357b8195aa2e'
end

客户端代码如下

@import SocketIO;

    NSString* socketUrlString = @"http://localhost:3000"";
   
    NSDictionary* config = @{@"log":@NO,@"forcePolling":@YES,@"reconnects":@YES};
    
    self.socketIOClient = [[SocketIOClient alloc] initWithSocketURL:[NSURL URLWithString:socketUrlString] config:config];
    
    [self.socketIOClient on:@"connect" callback:^(NSArray * data, SocketAckEmitter * ack) {
        NSLog(@"socketIOClientConnect");
        NSLog(@"data = %@",data);
        [self.socketIOClient emit:@"message" with:@[@"心跳包"]];
    }];
    
    
    [self.socketIOClient on:@"disconnect" callback:^(NSArray * data, SocketAckEmitter * ack) {
        NSLog(@"socketIOClientDisconnect");
        NSLog(@"data = %@",data);
        
    }];
    
    [self.socketIOClient on:@"error" callback:^(NSArray * data, SocketAckEmitter * ack) {
        NSLog(@"socketIOClientError");
        NSLog(@"data = %@",data);
       
    }];
    
    [_socketIOClient on:@"reconnect" callback:^(NSArray * data, SocketAckEmitter * ack) {
        NSLog(@"socketIOClientReconnect");
        NSLog(@"data = %@",data);

    }];
    
    [self.socketIOClient on:@"message" callback:^(NSArray * data, SocketAckEmitter * ack) {
        NSLog(@"socketIOClientMessage");
        NSLog(@"data = %@",data);
        NSString *string =data[0];
        NSLog(@"Received \"%@\"", string);
    }];
    
    [_socketIOClient connect];


好了可以测试了,注意因为设置的是localhost所以请用模拟器测试,否则需要执行ip。测试内容有2:

1、连上服务器以后,停掉服务器,客户端是否能检测到

2、客户端断网以后能否重练,是否有次数限制,时间限制

3、心跳包的处理

framework方式打包使用

由于swift语法还在不断更新,如果更新后需要更新代码进行编译,但是如果更新了代码则有可能就不能使用了,如果避免在swift语法更新后不重新编译也能使用?使用framework方式集成,因为已经将代码编译成了二进制文件,以后就更swift无关了。

下载 socket.io-client-swift代码,然后git checkout 1949b1fd487abb4301f57c608645357b8195aa2e

分别在模拟器和 Generic iOS Device下build,然后再合成

lipo -create **/**/*.framework/* **/**/*.framework/*   -output 输出地址/*


查看合成后情况

lipo -info /Users/zhangruquan/Downloads/trySwift/Debug-iphoneos/SocketIO.framework/SocketIO 

然后将Modules/SocketIO.swiftmodule里面的内容拷贝到一起。x86_64.swiftdoc、x86_64.swiftmodule、arm.swiftdoc、arm.swiftmodule、arm64.swiftdoc、arm64.swiftmodule

将加工后的framework拷贝到要使用的地方,项目上右键-》Targets-》General-》embedded Binaries-》+ 选中你的framework,如果是swift写的还要-》Build Settings-》Always Embed Swift Standard Libraries ,选择YES。

代码形式使用

拷贝代码到项目目录下,添加到项目里。设置-》Build Settings-》Packaging-》Defines Module -》Yes

新建头文件*-Bridging-Header.h,将其绝对路径复制到:设置-》Build Settings-》Swift compiler general-》Objective-C bridging Header。

在要使用的地方执行 #import “*-Swift.h”

Written on August 13, 2017