socket的基本使用

1、介绍。
socket是基于TCP的传输层协议,它是实现了浏览器与服务器的双向通讯。在 WebSocket API 中,浏览器和服务器只需要要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
2、socket的优点。
初次接触 WebSocket 的人,都会问同样的问题:我们已经有了 HTTP 协议,为什么还需要另一个协议?它能带来什么好处?

答案很简单,因为 HTTP 协议有一个缺陷:通信只能由客户端发起。

举例来说,我们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP 协议做不到服务器主动向客户端推送信息。

这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。我们只能使用"轮询":每隔一段时候,就发出一个询问,了解服务器有没有新的信息。最典型的场景就是聊天室。

3、socket中emit方法的使用。
emit主要用于端到端发送信息

socket.emit('action');//表示发送了一个action命令,命令是字符串的
//在另一端接收时,可以这么写: 
socket.on('action',function(){...});

socket.emit('action',data);//表示发送了一个action命令,还有data数据
//在另一端接收时,可以这么写:
 socket.on('action',function(data){...});

socket.emit(action,arg1,arg2); //表示发送了一个action命令,还有两个数据
//在另一端接收时,可以这么写: 
socket.on('action',function(arg1,arg2){...});

socket.emit(action,arg1,arg2,arg3,arg4); //如果是多个参数,就也应该知道什么意思了,同上

在emit方法中包含回调函数,例如:

socket.emit(‘action’,data, function(arg1,arg2){…} );那么这里面有一个回调函数可以在另一端调用,另一端可以这么写:socket.on(‘action’,function(data,fn){ fn(‘a’,‘b’) ; });

上面的data数据可以有0个或者多个,相应的在另一端改变function中参数的个数即可,function中的参数个数和顺序应该和发送时一致

上面的fn表示另一个端传递过来的参数,是个函数,写fn(‘a’,‘b’) ;会回调函数执行。一次发送不应该写多个回调,否则只有最后一个起效,回调应作为最后一个参数。
4、服务端的信息传输。

// send to current request socket client
socket.emit('message', "this is a test");
 
// sending to all clients except sender
socket.broadcast.emit('message', "this is a test");
 
// sending to all clients in 'game' room(channel) except sender
socket.broadcast.to('game').emit('message', 'nice game');
 
// sending to all clients, include sender
io.sockets.emit('message', "this is a test");
 
// sending to all clients in 'game' room(channel), include sender
io.sockets.in('game').emit('message', 'cool game');
 
// sending to individual socketid
io.sockets.socket(socketid).emit('message', 'for your eyes only');

上述集中方式为socket.io常用的数据传输方式,

io.sockets.on('connection', function (socket) {
 
});

回调函数的socket参数为一个 client 与服务器的连接标示,不同的 client 会有不同的连接标示。
5、不分组数据传输

  • socket.emit
socket.emit 信息传输对象为当前 socket 对应的 client ,各个client socket 相互不影响。
  • socket.broadcast.emit
socket.broadcast.emit 信息传输对象为所有 client ,排除当前socket 对应的 client 。
  • io.sockets.emit
信息传输对象为所有 client 。

6、分组数据传输
类似于之前提过的 of 方法生成命名空间来管理用户, socket.io 可以使用分组方法, socket.join() ,以及与之对应的 socket.leave() 。

io.sockets.on('connection', function (socket) {
  socket.on('firefox', function (data) {
    socket.join('firefox');
  });
  socket.on('chrome',function(data){
    socket.join('chrome');
  });
});

假设有两个聊天室,一个名为firefox,另一个为chrome,客户端操作

socket.emit('firefox') 就可以加入 firefox 聊天室;
socket.emit('chrome') 就可以加入 chrome 聊天室;

向一个分组传输消息,有两种方式:

socket.broadcast.to('chrome').emit('event_name', data);
  //emit to 'room' except this socket client
io.sockets.in('chrome').emit('event_name', data)
  //emit to all socket client in the room

broadcast 方法允许当前 socket client 不在该分组内。

可能有一个疑问,一个 socket 是否可以同时存在于几个分组,等效于一个用户会同时在几个聊天室活跃,答案是”可以“, socket.join() 添加进去就可以了。官方提供了订阅模式的示例:

socket.on('subscribe', function(data) { 
    socket.join(data.room);
})
 
socket.on('unsubscribe', function(data) { 
    socket.leave(data.room);
 })

后台处理订阅/退订事件

socket = io.connect('http://127.0.0.1:1338/');
socket.emit('subscribe',{"room" : "chrome"};
socket.emit('unsubscribe',{"room" : "chrome"};

前端触发订阅/退订事件,就可以加入对应的聊天室。 通过 of 方法也可以通过划分命名空间的方式,实现聊天室功能,但不如分组管理来的方便。

7、Socket.io难点大放送(暂时没有搞定)
授权验证
socket 连接需要添加权限验证,让已登录的用户 socket 连接到服务器,未登录的用户无条件拒绝。全局授权管理如下:

io.sockets.authorization(function (handshakeData, callback) {
     callback(null, true);
}).

callback 函数有两个参数,第一个为 error ,第二个参数为是否授权bool值,通过授权回调函数应为 callback(null,true) ,其它情况下都为拒绝建立连接。

按照web的开发方式,检测是否登录首选 cookie-session 来实现,问题也是出在这里。 websocket 握手阶段属于 HTTP 协议,简单来说是可以读到cookie,就可以实现session。

  • 精准单用户推送
    理论上来说
// sending to individual socketid
io.sockets.socket(socketid).emit('message', 'for your eyes only');

就可以向一个特定用户推送消息,但是如何获得这个 socketId ,就是生成一个哈希数组,key为username,值为socket.id,这样就可以通过用户名获取对应的id,进而可以向特定client推送消息。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值