.net版Socketio4net类库和java版socket.io-java-client类库 连接socket.io 1.4版本都不行,网上大多是socket.io 0.9版本的,socket.io 更新之后就不支持了。本人已研究

成功连接socket.io 1.4版本的方法,例子采用C#。

  一、socket.io 几个重要要文件

   1、node_modules\socket.io\node_modules\engine.io\node_modules\engine.io-parser\lib\index.js  

var packets = exports.packets = {
open: 0 // non-ws
, close: 1 // non-ws
, ping: 2
, pong: 3
, message: 4
, upgrade: 5
, noop: 6
};

    这几个是定义消息类型的 websocket连接的时候在open事件里需要发送一个send("5[\"simple\",{\"name\":\"simple\"}]"); 类型为5的消息。

    

exports.decodePacket = function (data, binaryType, utf8decode) {
// String data
console.log('解析数据'+data);
if (typeof data == 'string' || data === undefined) {
if (data.charAt(0) == 'b') {
return exports.decodeBase64Packet(data.substr(1), binaryType);
} var type = data.charAt(0); if (utf8decode) {
try {
data = utf8.decode(data);
} catch (e) {
return err;
}
}
console.log('解析数据3:'+type);
if (Number(type) != type || !packetslist[type]) {
return err;
} if (data.length > 1) {
return { type: packetslist[type], data: data.substring(1) };
} else {
return { type: packetslist[type] };
}
} // Binary data
if (binaryType === 'arraybuffer') {
var type = data[0];
var intArray = new Uint8Array(data.length - 1);
for (var i = 1; i < data.length; i++) {
intArray[i - 1] = data[i];
}
return { type: packetslist[type], data: intArray.buffer };
}
var type = data[0];
return { type: packetslist[type], data: data.slice(1) };
};

   从客户端发过来的消息会从这里解析出来,得到消息类型。

   2、node_modules\socket.io\node_modules\engine.io\lib\socket.js

     从上面解析出来的消息字符串会到这里

Socket.prototype.onPacket = function (packet) {
console.log('engine.io-lib-Socket.js==OnPacket///'+packet);
if ('open' == this.readyState) {
// export packet event
debug('packet');
this.emit('packet', packet); // Reset ping timeout on any packet, incoming data is a good sign of
// other side's liveness
this.setPingTimeout();
console.log('engine.io-lib-Socket.js==OnPacket>>>'+packet.type);//upgrade
switch (packet.type) { case 'ping':
debug('got ping');
this.sendPacket('pong');
this.emit('heartbeat');
break; case 'error':
this.onClose('parse error');
break; case 'message':
this.emit('data', packet.data);
this.emit('message', packet.data);
break;
}
} else {
debug('packet received with closed socket');
console.log('packet received with closed socket');
}
};

   3、node_modules\socket.io\node_modules\socket.io-parser\index.js

function decodeString(str) {
console.log('socket.io-parser-index.js-encodeAsString4---'+str);
var p = {};
var i = 0; // look up type
p.type = Number(str.charAt(0));
if (null == exports.types[p.type]) return error(); // look up attachments if type binary
if (exports.BINARY_EVENT == p.type || exports.BINARY_ACK == p.type) {
console.log("---------1");
var buf = '';
while (str.charAt(++i) != '-') {
buf += str.charAt(i);
if (i == str.length) break;
}
if (buf != Number(buf) || str.charAt(i) != '-') {
throw new Error('Illegal attachments');
}
p.attachments = Number(buf);
} // look up namespace (if any)
if ('/' == str.charAt(i + 1)) {
p.nsp = '';
while (++i) {
var c = str.charAt(i);
if (',' == c) break;
p.nsp += c;
if (i == str.length) break;
}
} else {
p.nsp = '/';
} // look up id
var next = str.charAt(i + 1);
if ('' !== next && Number(next) == next) {
p.id = '';
while (++i) {
var c = str.charAt(i);
if (null == c || Number(c) != c) {
--i;
break;
}
p.id += str.charAt(i);
if (i == str.length) break;
}
p.id = Number(p.id);
} // look up json data
if (str.charAt(++i)) {
try {
console.log("---------21/"+str.substr(i));
p.data = json.parse(str.substr(i));
} catch(e){
return error();
}
}
console.log(p);
debug('decoded %s as %j', str, p);
return p;
}
exports.types = [
'CONNECT',
'DISCONNECT',
'EVENT',
'ACK',
'ERROR',
'BINARY_EVENT',
'BINARY_ACK'
]; /**
* Packet type `connect`.
*
* @api public
*/ exports.CONNECT = 0; /**
* Packet type `disconnect`.
*
* @api public
*/ exports.DISCONNECT = 1; /**
* Packet type `event`.
*
* @api public
*/ exports.EVENT = 2; /**
* Packet type `ack`.
*
* @api public
*/ exports.ACK = 3; /**
* Packet type `error`.
*
* @api public
*/ exports.ERROR = 4; /**
* Packet type 'binary event'
*
* @api public
*/ exports.BINARY_EVENT = 5; /**
* Packet type `binary ack`. For acks with binary arguments.
*
* @api public
*/ exports.BINARY_ACK = 6;

    然后消息会传递到这里,再解析它。

     4、node_modules\socket.io\node_modules\socket.io-parser\node_modules\component-emitter\index.js

    最后消息会到这里找到对应的回调函数。

Emitter.prototype.emit = function(event){

 // console.log(arguments);
// console.log("event");
//console.log(event);
// console.log("_callbacks");
// console.log( this._callbacks);
this._callbacks = this._callbacks || {};
var args = [].slice.call(arguments, 1)
, callbacks = this._callbacks[event];
//console.log('args');
//console.log(args);
//console.log('callbacks'); if (callbacks) {
// console.log('回调 正确');
callbacks = callbacks.slice(0); console.log(callbacks);
for (var i = 0, len = callbacks.length; i < len; ++i) {
callbacks[i].apply(this, args);
// console.log('执行 正确');
}
}
else
{
console.log('回调 出错');
} return this;
};

  二、socket.io授权

    1、.net授权获取sid

       授权地址http://127.0.0.1:3000/socket.io/?eio=3&transport=polling&t=1404421022936,0.9版本的socket.io授权不一样,通过这个授权地址返回

    sessionid,如下格式 0{"sid":"BrB2vsiK79ZoLdMcAAAK","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":60000},解析得到sid.

protected SocketIOHandshake requestHandshake(Uri uri)
{
string value = string.Empty;
string errorText = string.Empty;
SocketIOHandshake handshake = null; using (WebClient client = new WebClient())
{
try
{
client.Headers.Add("cookie:io=3435456567567567355");
// client.Headers.Add("cookie:express.sid=3435456567567567355");
//client.Headers.Add("cookie:sid=3435456567567567355");
value = client.DownloadString("http://127.0.0.1:3000/socket.io/?eio=3&transport=polling&t=1404421022936");
int ii = value.IndexOf("\",");
int im = value.IndexOf("\":\"");
value = value.Substring(im+, ii-im-);
//value = "3435456567567567355";
//value = client.DownloadString(string.Format("{0}://{1}:{2}/socket.io/1/{3}", uri.Scheme, uri.Host, uri.Port, uri.Query)); // #5 tkiley: The uri.Query is available in socket.io's handshakeData object during authorization
value = value+":55000:60000:websocket";
if (string.IsNullOrEmpty(value))
errorText = "Did not receive handshake string from server";
}
catch (Exception ex)
{
errorText = string.Format("Error getting handsake from Socket.IO host instance: {0}", ex.Message);
//this.OnErrorEvent(this, new ErrorEventArgs(errMsg));
}
}
if (string.IsNullOrEmpty(errorText))
handshake = SocketIOHandshake.LoadFromString(value);
else
{
handshake = new SocketIOHandshake();
handshake.ErrorMessage = errorText;
} return handshake;
}

      以下是socket.io接收到的授权消息,能够取到客户端传来的cookie,可以用过控制重复登录。

io.set('authorization', function(handshakeData, callback) {
// callback(handshakeData, true);
callback(null, true);
return
if (handshakeData.headers.cookie) {
//console.log(handshakeData.headers.cookie);
handshakeData.cookie = cookie.parse(handshakeData.headers.cookie);
//console.log(handshakeData.cookie);
handshakeData.cookie['express.sid']=handshakeData.cookie.io;
handshakeData.sessionID = handshakeData.cookie['express.sid'];
//console.log(handshakeData.sessionID);
//console.log(handshakeData.cookie['express.sid']); console.log("handshakeData:" + handshakeData.headers.cookie + "-----" + handshakeData.cookie); //var connect_sid = handshakeData.cookie['connect.sid'];
//console.log("connect_sid="+connect_sid);
handshakeData.session = handshakeData.sessionID;
if (handshakeData.cookie['express.sid'] == handshakeData.sessionID) {
console.log('1-true');
return callback(null, true);
}
//return callback('Cookie is invalid.', false);
}
else {
console.log('12-err');
//return callback('No cookie transmitted.', false);
}
});

  三、websocket 连接

     websocket连接地址ws://127.0.0.1:3000/socket.io/?eio=3&t=124324324324&transport=websocket&sid=" + this.HandShake.SID,这个很重要

public void Connect()
{
lock (padLock)
{
if (!(this.ReadyState == WebSocketState.Connecting || this.ReadyState == WebSocketState.Open))
{
try
{
this.ConnectionOpenEvent.Reset();
this.HandShake = this.requestHandshake(uri);// perform an initial HTTP request as a new, non-handshaken connection if (this.HandShake == null || string.IsNullOrWhiteSpace(this.HandShake.SID) || this.HandShake.HadError)
{
this.LastErrorMessage = string.Format("Error initializing handshake with {0}", uri.ToString());
this.OnErrorEvent(this, new ErrorEventArgs(this.LastErrorMessage, new Exception()));
}
else
{
String sss = "ws://127.0.0.1:3000/socket.io/?eio=3&t=124324324324&transport=websocket&sid=" + this.HandShake.SID;
//sss = "ws://127.0.0.1:3000/socket.io/?transport=polling&t=12434324324324&sid=" + this.HandShake.SID;
//string.Format("{0}://{1}:{2}/socket.io/1/websocket/{3}", wsScheme, uri.Host, uri.Port, this.HandShake.SID)
string wsScheme = (uri.Scheme == Uri.UriSchemeHttps ? "wss" : "ws");
this.wsClient = new WebSocket(
sss,
string.Empty,
this.socketVersion);
this.wsClient.EnableAutoSendPing = false; // #4 tkiley: Websocket4net client library initiates a websocket heartbeat, causes delivery problems
this.wsClient.Opened += this.wsClient_OpenEvent;
this.wsClient.MessageReceived += this.wsClient_MessageReceived;
this.wsClient.Error += this.wsClient_Error; this.wsClient.Closed += wsClient_Closed; this.wsClient.Open();
}
}
catch (Exception ex)
{
Trace.WriteLine(string.Format("Connect threw an exception...{0}", ex.Message));
this.OnErrorEvent(this, new ErrorEventArgs("SocketIO.Client.Connect threw an exception", ex));
}
}
}
}

    连接之后在open 事件里需要发送一个类型为5(upgrade 心跳)的消息websocket.send("5[\"simple\",{\"name\":\"simple\"}]");,然后websocket会收到一个“40”消息,

   40代表连接功能了,可以进行通信了。

  一般发送消息的格式为:"42[\"simple\",{\"name\":\"tstssss\"}]"

  42:代表消息类型,simple为socket.io的事件名称。

  四、定时发送心跳数据

      授权的时候能获取到"pingInterval":25000,"pingTimeout":60000 心跳间隔和超时的时间,需要每隔 pingInterval 时间 发送一次心跳数据才能保存不断开连接。

    send("5:::");

  五、带回调函数的方法

    服务器回调:

    socket.io 服务器端给客户端发送数据带回调函数如下:

  socket.emit('newuser','newuser-data',function(m,d){
console.log(m);
console.log(d);
});

   客户端接收到的数据形式如下: 420["newuser","newuser-data"] 或 4290203["newuser","newuser-data"]

   其中4代表:message,2代表:event ,0 ,90203 代表:回调函数的事件ID号,事件ID号是不固定的

   如果客户端收到消息,服务器需要触发回调函数时:

   this.send("430[\"newuser\",{\"name\":\"simple\"}]");

   this.send("4390203[\"newuser\",{\"name\":\"simple\"}]");

   其中 3代表:ack 回调, “newuser”必须和原有名字一致。

    客户端回调:

  

    socket.on('messageAck', function (data,fn) {
console.log(data);
//console.log(fn);
fn('aaa','bb','cc',{id:1});
});

   客户端发送 this.send("423[\"messageAck\",\"ssssssssssssssssss\"]"); ,3 代表消息ID

服务器收到信息之后 回立马发送  “433["messageAck",.........]” 到客户端

    

    

.net , java webSocket 连接 Socket.io (1.4.4版本) 问题的更多相关文章

  1. AndroidAsync :异步Socket,http(client+server),websocket和socket.io的Android类库

    AndroidAsync是一个用于Android应用的异步Socket,http(client+server),websocket和socket.io的类库.基于NIO,没有线程.它使用java.ni ...

  2. 即时通信WebSocket 和Socket.IO

    WebSocket HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯. 在2008年诞生,2011年成为国际标准. 现在基本所有浏览器都已经支持了. We ...

  3. websocket与socket.io

    什么是Websocket? Websocket是一个独立于http的实时通信协议,最初是在HTML5中被引用进来的,在HTML5规范中作为浏览器与服务器的核心通信技术被嵌入到浏览器中.WebSocke ...

  4. 长连接 Socket.IO

    概念 说到长连接,对应的就是短连接了.下面先说明一下长连接和短连接的区别: 短连接与长连接 通俗来讲,浏览器和服务器每进行一次通信,就建立一次连接,任务结束就中断连接,即短连接.相反地,假如通信结束( ...

  5. websocket 与Socket.IO介绍

    一  websocket WebSocket是html5新增加的一种通信协议,目前流行的浏览器都支持这个协议,例如 Chrome,Safrie,Firefox,Opera,IE等等,对该协议支持最早的 ...

  6. websocket 和 socket.io 之间的区别是什么

    socket.io封装了websocket,同时包含了其它的连接方式,比如Ajax.原因在于不是所有的浏览器都支持websocket,通过socket.io的封装,你不用关心里面用了什么连接方式.你在 ...

  7. websocket 和 socket.io 之间的区别

    socket.io封装了websocket,同时包含了其它的连接方式,比如Ajax.原因在于不是所有的浏览器都支持websocket,通过socket.io的封装,你不用关心里面用了什么连接方式.你在 ...

  8. 轮询以及webSocket与socket.io原理

    概述: 首先,我们知道,起初的http协议只是为了能够进行通信而被创造出来(也就是请求-响应的过程).并没有双向通信这一说,后面随着历史业务的需求,人们使用轮询http来解决双向通信也就是使用xhr或 ...

  9. Socket.io在线聊天室

    从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发.Nodejs框架是基于V8的引擎,是目前速度最快的Javascript引擎.chrome浏 ...

随机推荐

  1. jTemplates模板学习笔记

    1.jTemplates工作方式   1)setTemplateElement:指定可处理的模板对象 2)processTemplate:对模板化的对象进行数据处理 2.语法解析   1)jTempl ...

  2. PLSQL Developer连接远程Oracle方法(非安装client)

    远程连接Oracle比較麻烦,通常须要安装oracle的客户端才干实现. 通过instantclient能够比較简单的连接远程的Oracle. 1.新建文件夹D:\Oracle_Cleint用于存放相 ...

  3. [Functional Programming ADT] Combine Multiple State ADT Based Redux Reducers

    Redux provides a convenient helper for combining many reducers called combineReducer, but it focuses ...

  4. 网页制作,网站制作中put和get的区别

    Http定义了与服务器交互的不同方法,最基本的方法有4种,分别是GET,POST,PUT,DELETE.URL全称是资源描述符,我们可以这样认为:一个URL地址,它用于描述一个网络上的资源,而HTTP ...

  5. 解决Xcode 6 编译Cocos2d-x iOS项目失败

    在Xcode 6 beta里编译Cocos2d-x iOS项目时可能会失败,提示如下错误: Undefined symbols for architecture i386: "_fwrite ...

  6. 11g OCM 考试感悟

    11g OCM 考试感悟 PrudentWoo 累,累.真的很累.考前每天全场景的刷两遍.三遍不觉得累.总感觉练习时间不够.考中尽管时间足够.可是压力很大.尤其看到一些和平时训练不一样题目的时候,那种 ...

  7. vue 不能检测数组长度 值变化原因解析

    1.vue不能检测数组长度或者值的变化 (1)数组长度变化 未检测到 <!DOCTYPE html> <html lang="en"> <head&g ...

  8. c++11 Using Callable Objects, std::thread, std::bind, std::async, std::call_once

  9. 【VBA编程】09.使用Excle集合对象

    使用Workbooks工作簿集合.工作簿对象.工作表集合.工作表对象,并且观察使用Add方法前后工作簿与工作表数目的变化 [代码区域] Sub 测试集合工作簿() Dim wbs As Workboo ...

  10. Debian9.3安装NW360无线网卡驱动

    最近想把家里的一台老旧台式机利用起来,打算安装Debian9.3,下载ISO,用PowerISO写入到U盘,然后开始安装,过程基本顺利. 就是中间提示缺少“rtl_nic/rtl8105e-1.fw” ...