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

本文介绍了如何使用Java socket.io-java-client库成功连接到Socket.io 1.4.4版本,重点讲解了关键文件、消息解析流程、授权机制以及WebSocket连接步骤,还涉及到心跳维持和回调函数的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

.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的消息。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

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) {returnerr;

}

}

console.log('解析数据3:'+type);if (Number(type) != type || !packetslist[type]) {returnerr;

}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

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

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

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

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

functiondecodeString(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]) returnerror();//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){returnerror();

}

}

console.log(p);

debug('decoded %s as %j', str, p);returnp;

}

View Code

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

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

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

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

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.

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

protectedSocketIOHandshake requestHandshake(Uri uri)

{string value = string.Empty;string errorText = string.Empty;

SocketIOHandshake handshake= null;using (WebClient client = newWebClient())

{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= newSocketIOHandshake();

handshake.ErrorMessage=errorText;

}returnhandshake;

}

View Code

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

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

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,这个很重要

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public voidConnect()

{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, newException()));

}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 = newWebSocket(

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的事件名称。

四、定时发送心跳数据

授权的时候能获取到"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",.........]” 到客户端

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值