转载

.net , java webSocket 连接 Socket.io (1.4.4版本) 问题

.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) }; };  View Code

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

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');   } };  View Code

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; }  View Code
  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;  View Code

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

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; };  View Code

二、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+3, ii-im-3);                     //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;         }  View Code

以下是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);     }      });  View Code

三、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));                     }                 }             }         }  View Code

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

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

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

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

原文  http://www.cnblogs.com/netuml/p/5141345.html
正文到此结束
Loading...