nodejs即时通讯模块+SocketIO4Net的使用小结
实现思路:客户端js连接了nodejs服务,通过.net连接nodejs服务,通过.net发送消息到nodejs,然后通过nodejs将消息推送给(用户)客户端
1、先下载nodejs安装,至于怎么安装nodejs网上很多说明,这里就不做说明了
SocketIO4Net开源项目结构如下:
进入项目的目录:socketio4net-develop\samples\node.server 如图下图:
双击先 install.cmd运行这个文件安装nodejs需要的模块(这个步骤需要在已经连接网络下进行),在双击运行startServer.cmd文件启动nodejs服务,服务启动成功入下图:
使用nodejs可以快速搭建一个即时通讯的聊天室下载请点这里
使用下载SocketIO4Net开源类库可以快速链接nodejs通讯服务进行交互通讯
SocketIO4Net的项目里面有个控制台Console_Events项目下有个EventClient.cs类,进行二次开发主要参照这个类的写法去开发,加入自己的逻辑
我做测试修改的EventClient.cs类的代码如下:
using System; using System.Diagnostics; using System.Threading; using SocketIOClient; using Newtonsoft.Json.Linq; using System.Linq; using System.Text.RegularExpressions; using SocketIOClient.Messages; using System.Net; namespace ConsoleEvents { /// <summary> /// Example usage class for SocketIO4Net /// </summary> public class EventClient { Client socket; public void Execute() { Console.WriteLine("Starting SocketIO4Net Client Events Example..."); socket = new Client("http://127.0.0.1:3000/") { }; // url to the nodejs / socket.io instance //socket.TransportPeferenceTypes.Add(TransportType.XhrPolling); socket.Opened += SocketOpened; socket.Message += SocketMessage; socket.SocketConnectionClosed += SocketConnectionClosed; socket.Error += SocketError; // Optional to add HandShake headers - comment out if you do not have use socket.HandShake.Headers.Add("OrganizationId", "1034"); socket.HandShake.Headers.Add("UserId", "TestSample"); socket.HandShake.Headers.Add("Cookie", "somekookie=magicValue"); socket.HandShake.Headers.Add("token", "Fxt_ABCDEFGHIJKLMNOPQRSTUVWXYZ"); // Register for all On Events published from the server - prior to connecting // register for 'connect' event with io server socket.On("connect", (fn) => { Console.WriteLine("\r\nConnected event...{0}\r\n", socket.ioTransport.TransportType); socket.Emit("subscribe", new { room = "eventRoom" }); // client joins 'eventRoom' on server }); // register for 'update' events - message is a json 'Part' object socket.On("update", (data) => { Console.WriteLine("recv [socket].[update] event"); Console.WriteLine(" raw message: {0}", data.RawMessage); Console.WriteLine(" string message: {0}", data.MessageText); Console.WriteLine(" json data string: {0}", data.Json.ToJsonString()); // cast message as Part - use type cast helper Part part = data.Json.GetArgAs<Part>(); Console.WriteLine(" PartNumber: {0}\r\n", part.PartNumber); }); // register for 'alerts' events - broadcast only to clients joined to 'Room1' socket.On("log", (data) => { Console.WriteLine(" log: {0}", data.Json.ToJsonString()); }); socket.On("empty", (data) => { Console.WriteLine(" message 'empty'"); }); //socket.Connect(SocketIOClient.TransportType.XhrPolling); socket.Connect(); } public void SendMessageSamples() { // random examples of different styles of sending / recv payloads - will add to... //socket.Send(new TextMessage("Hello from C# !")); // send plain string message //socket.Emit("hello", new { msg = "My name is SocketIO4Net.Client!" }); // event w/string payload //socket.Emit("sendtodepartment", new { token = "Fxt_ABCDEFGHIJKLMNOPQRSTUVWXYZ", todepartmentids = "user_123_123,user_1234_1234,user_12345_12345", msg = "eeeeeeeeeeeeeeeeeeeeee" }); // socket.Emit("sendtousers", new { token = "Fxt_ABCDEFGHIJKLMNOPQRSTUVWXYZ", touserids = "user_123w_123q,user_1234_1234,user_12345_12345", msg = "xxxxxxxxxxxxxxxxxxxxxxxxx" }); socket.Emit("sendMsg", new { token = "qfefefedfwrfwefw4teryurtyewtwerwererererwe", UserId = "1", UserName = "test", msg = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }); //socket.Emit("heartbeat"); // event w/o data payload (nothing to do with socket.io heartbeat) //socket.Emit("hello", "simple string msg"); //socket.Emit("partInfo", new { PartNumber = "AT80601000741AA", Code = "SLBEJ", Level = 1 }); // event w/json payload //Part newPart = new Part() { PartNumber = "K4P2G324EC", Code = "DDR2", Level = 1 }; //socket.Emit("partInfo", newPart); // event w/json payload // callback using namespace example //Console.WriteLine("Emit [socket.logger].[messageAck] - should recv callback [socket::logger].[messageAck]"); //socket.Emit("messageAck", new { hello = "papa" }, "", // (callback) => // { // var jsonMsg = callback as JsonEncodedEventMessage; // callback will be of type JsonEncodedEventMessage, cast for intellisense // Console.WriteLine(string.Format("callback [socket::logger].[messageAck]: {0} \r\n", jsonMsg.ToJsonString())); // }); } void SocketError(object sender, ErrorEventArgs e) { Console.WriteLine("socket client error:"); Console.WriteLine(e.Message); } void SocketConnectionClosed(object sender, EventArgs e) { Console.WriteLine("WebSocketConnection was terminated!"); } void SocketMessage(object sender, MessageEventArgs e) { // uncomment to show any non-registered messages if (string.IsNullOrEmpty(e.Message.Event)) Console.WriteLine("Generic SocketMessage: {0}", e.Message.MessageText); else Console.WriteLine("Generic SocketMessage: {0} : {1}", e.Message.Event, e.Message.JsonEncodedMessage.ToJsonString()); } void SocketOpened(object sender, EventArgs e) { } public void Close() { if (this.socket != null) { socket.Opened -= SocketOpened; socket.Message -= SocketMessage; socket.SocketConnectionClosed -= SocketConnectionClosed; socket.Error -= SocketError; this.socket.Dispose(); // close & dispose of socket client } } } }
修改server.js测试代码如下
process.env['DEBUG'] = 'server:*'; var config = require('./config.json'), debug = { io: require('debug')('server:io'), app: require('debug')('server:app'), server: require('debug')('server:server'), config: require('debug')('server:config'), error: require('debug')('server:error') }, http = require('http'), express = require('express'), app = express(), util = require('util'), socketio = require('socket.io'), socketioWildcard = require('socket.io-wildcard'), server, io, userArray = [], token = "qfefefedfwrfwefw4teryurtyewtwerwererererwe"; //server = http.createServer(app), //io = socketio.listen(server), webApi = require('./routes/api'), store = require('./store'); // cheap key-value stand-in for redis // Splash Info debug.config(''); debug.config('SocketIO4Net Sample Server\r\n'); debug.config('\tNodejs: %s', process.version); debug.config('\tsocket.io: v%s', socketio.version); debug.config('\tListening on port %d', config.web.port); debug.config(''); // ******************************* // Configure Express // ******************************* app.configure('development', function () { // only in development app.use(logErrors); }); app.configure(function () { app.use(express.favicon()); app.use(express.bodyParser()); app.use(express.compress()); app.use(express.methodOverride()); app.use(errorHandler); // serve static assets from these folder app.use('/scripts', express.static('scripts')); app.use('/content', express.static('content')); app.use('/app', express.static('app')); // basic usage logging app.use(function (req, res, next) { // console.log('%s %s', req.method, req.url); if (req.url.indexOf('/api') === 0) { store.incr('app.apiCount'); } //watchBcast('log', { level: 5, zone: 'app', eventCode: 'request', message: 'url', data: { 'method': req.method, 'url': req.url, 'count': cnt } }); next(); }); }); //var socketio1 = io.listen(server); server = http.createServer(app).listen(config.web.port); //io = socketio.listen(server); io = socketioWildcard(socketio).listen(server); // General Handlers app.get('/api/:target', webApi.get); app.get('/config', function (req, res) { res.send(config.clientConfiguration); }); app.get('/', function (req, res) { store.incr('app.visits'); res.sendfile(__dirname + '/index.html'); watchBcastAnalytics(); }); // ******************************* // Configure socket.io // ******************************* io.enable('browser client minification'); // send minified client io.enable('browser client etag'); // apply etag caching logic based on version number io.enable('browser client gzip'); // gzip the file io.set('log level', 1); // reduce logging: 0-error, 1-warn, 2-info, 3-debug io.set('transports', ['websocket', 'xhr-polling', 'jsonp-polling', 'htmlfile']); // ******************************* // socket.io handlers // ******************************* io.sockets.on('connection', function (socket) { // initial connection from a client var transport = io.transports[socket.id].name, key = transport === 'websocket' ? 'websocket' : 'other'; store.incr('io.connection.' + key); debug.io('client connection: %s', transport); watchBcastAnalytics(); watchBcast('log', { zone: 'io', eventCode: 'connection', message: 'connection' }); // bcast connection count to 'watch' room watchBcast('log', { zone: 'server', eventCode: 'api', message: webApi.statusCounts() }); socket.on('*', function onWildcard(event) { watchBcast('log', { zone: 'io', eventCode: event.name || '?', message: util.inspect(event) }); }); socket.on('message', function (data) { watchBcast('log', { zone: 'client', eventCode: 'message', message: data }); }); socket.on('echo', function (message) { socket.emit('echo', message); }); socket.emit('news', { hello: 'world' }); socket.on('clientBroadcast', function (message) { var combinedMsg; try { if (message.room) { combinedMsg = [message.room, message.event]; socket.broadcast.to(message.room).emit(message.event, message.data); //emit to 'room' except this socket } else { combinedMsg = [message.event]; socket.broadcast.emit(message.event, message.data); //emit to all sockets except this one } //watchBcast('log', { zone: 'clientBroadcast', eventCode: combinedMsg, message: message.data }); } catch (err) { debug.io('clientBroadcast error', message, err); store.incr('io.errors'); watchBcastAnalytics(); } }); // client request to join 'room' data.room by name socket.on('subscribe', function (event) { socket.join(event.room); if (event.room === 'watch') { socket.emit('analytics', webApi.statusCounts()); } }); // client request to leave 'room' data.room by name socket.on('unsubscribe', function (event) { socket.leave(event.room); }); socket.on('disconnect', function () { // client-server connection is closed store.decr('io.connection.' + key); watchBcastAnalytics(); watchBcast('log', { zone: 'io', eventCode: 'disconnect', message: 'client' }); for (var loop = 0; loop < userArray.length; loop++) { if (userArray[loop].SocketId == socket.id) { userArray.splice(loop, 1); console.log("disconnect", "client-server connection is closed"); //delete users[loop]; break; } } }); socket.on('userLogin', function (paraData) { //用户登录(客户端与服务端(nodejs)服务连接入口) , paraData 是客户登录时传过来的数据一个js对象 var user = {}; user.SocketId = socket.id; user.UserId = paraData.UserId; user.UserName = paraData.UserName; user.Socket = socket; userArray.push(user); //添加用户的登录 console.log('用户登录成功: ', user); }); socket.on('sendMsg', function (data) { //发送消息给用户 data是通过(,net)后端发送过来的数据,经过此事件推送到客户端(用户) console.log('sendMsg: ', data); if (data.token == token) { if (data.UserId != "0") { //推送给单个用户 for (var i = 0; i < userArray.length; i++) { if (userArray[i].UserId == data.UserId) { userArray[i].Socket.emit('message', data); //将消息推送到客户端 break; } } } else { //推送给全部用户 for (var j = 0; j < userArray.length; j++) { userArray[j].Socket.emit('message', data); //将消息推送到客户端 } } } else { console.log('token Error!'); } }); }); // ******************************* // Error Logging / broadcast helpers // ******************************* function watchBcast(event, data) { try { data.dateTime = new Date(Date.now()); io.sockets.in('watch').emit(event, data); debug.io(util.inspect(data)); } catch (err) { debug.error('watchBcast error: %s', err); store.incr('io.errors'); } } function watchBcastAnalytics() { watchBcast('analytics', webApi.statusCounts()); } function logErrors(err, req, res, next) { store.incr('app:errors'); var status = err.statusCode || 500; debug.io(status + ' ' + (err.message ? err.message : err)); if (err.stack) { debug.error(err.stack); } watchBcastAnalytics(); next(err); } function errorHandler(err, req, res, next) { var status = err.statusCode || 500; if (err.message) { res.send(status, err.message); } else { res.send(status, err); } watchBcastAnalytics(); } process.on('uncaughtException', function (err) { // handle the error safely debug.error(err); store.incr('app:errors'); watchBcastAnalytics(); });
客户端代码:
<!DOCTYPE html> <html> <body> <h1>WebSocket</h1> <script src="http://127.0.0.1:3000/socket.io/socket.io.js"></script> <script type="text/javascript"> window.onload = (function () { var iosocket = io.connect("ws://127.0.0.1:3000/"); iosocket.on("connect", function () { iosocket.emit('userLogin', { UserName: "123q", UserId: "1" }); iosocket.on("message", function (msg) { //alert(JSON.stringify(msg)); document.getElementById("conent").innerText = JSON.stringify(msg); }); }); }); </script> <div id="conent"></div> </body> </html>
整个过程主要操作emit事件
完整的测试代码:http://pan.baidu.com/s/1slvstgp 密码:ccie