socket.io / 连接参数
Posted
技术标签:
【中文标题】socket.io / 连接参数【英文标题】:socket.io / parameters on connection 【发布时间】:2014-09-24 20:29:44 【问题描述】:在我的 node.js / Express.js 应用程序中,我需要通过 socket.io 连接传递参数(在另一篇文章中看到)。
在客户端,我有类似的东西:
编辑
var socket = io.connect('/image/change', query:"name=my_img_name");
var siofu = new SocketIOFileUpload(socket);
siofu.listenOnInput(document.getElementById("change_image_inpt"));
在服务器端:
编辑
io.of('/image/change')
.on('connection', function (socket)
console.log('log input param : ' + socket.handshake.query.name);
);
但控制台中什么也没有。
还有其他方法可以实现吗?
edit2
这是客户端的完整代码:
$(document).ready(function()
// icon_action_modal
$('.icon_actions').on('click', function()
// set icon preview
$('#icon_action_modal_icon_preview').html('<img src="/upload/icon/' + $(this).data('icon') + '.png" />');
// set icon to delete
$('#icon_name').val($(this).data('icon'));
// set Change icon socket
var socket = io.connect('/icon_sets/change', query:"name=my_img_name");
var siofu = new SocketIOFileUpload(socket);
siofu.listenOnInput(document.getElementById("change_icon"));
// Do something when a file is uploaded
siofu.addEventListener("complete", function ()
$('.overlay').hide();
);
// display loader window
socket.on('displayOverlay', displayOverlay);
// display
socket.on('displayIconImage', function (data)
$('#iconset_render').append('<div class="icon"><img src="' + data.path + '" /></div>');
);
socket.on('setIconsetArray', function (data)
var iconset = ($('#iconset_array').val()) ? JSON.parse($('#iconset_array').val()) : [];
iconset.push(data.iconName);
$('#iconset_array').val(JSON.stringify(iconset));
deleteIcon($('#icon_name').val());
// close modal
$('#icon_action_modal').modal('hide');
);
);
$('#icon_action_modal_delete_icon').on('click', function()
deleteIcon($('#icon_name').val());
// close modal
$('#icon_action_modal').modal('hide');
);
); // end document.ready
以及服务器端的完整代码:
io.of('/icon_sets/change')
.on('connection', function (socket)
console.log('log input param : ' + socket.handshake.query.name);
functions.socketImageTransfer(socket, 'icon', 65, 65);
);
使用socketImageTransfer
功能:
module.exports.socketImageTransfer = function(socket, type, width, height, name)
var socketioFileUploadServer = require('socketio-file-upload'); // upload files by socket
var config = require(__dirname + '/config/config.json');
var easyimg = require('easyimage'); // crop - resize image
var fs = require('fs'); // file system access
// Make an instance of socketioFileUploadServer and listen on this socket:
var uploader = new socketioFileUploadServer();
uploader.dir = config.tmpDir;
uploader.listen(socket);
// Do something when a file is saved:
uploader.on('saved', function (event)
console.log('Original ' + type + ' saved');
// resize and rename image with a unique id
var newName;
if (!name)
newName = Math.random().toString(36).substr(2, 9) + '_' + type + '.png';
else
newName = name;
var fileName = event.file.name.replace(/ /g, '_');
easyimg.rescrop(src: config.tmpDir + fileName, dst: config.uploadDir + type + '/' + newName, width: width, height: height, function (err, image)
if (err) return console.log(err);
console.log(type + ' resized and cropped: ' + image.width + ' x ' + image.height);
// image is uploaded - resized - croped, now display it
socket.emit('display' + ucfirst(type) + 'Image', path: '/upload/'+ type + '/' + newName);
// remove original from file system
fs.unlink(config.tmpDir + fileName, function ()
if (err) throw err;
console.log('Original ' + type + ' removed');
);
// additionnal action
switch(type)
case 'icon':
// send path to generate iconset_json
socket.emit('setIconsetArray', iconName: newName);
break;
);
);
uploader.on('start', function (event)
console.log('Client start upload');
socket.emit('displayOverlay');
);
// Error handler:
uploader.on('error', function (event)
console.log("Error from uploader", event);
);
;
感谢您的帮助
【问题讨论】:
如果控制台中没有任何内容,您的connection
处理程序根本不会触发,因为至少undefined
应该在控制台中。可能您在其他地方有错误以及我在回答中描述的错误。
您的代码似乎在工作,除了一件事:您声明 socket
,但将 socket2
传递给 SocketIOFileUpload
构造函数。
是的,对不起,在我的代码中,套接字的真实名称是`socket2。但正如我在你的回答中所说,这段代码是在我想要之前执行的......它是在我启动服务器时执行的。而此时,包含socket代码的客户端文件并没有被包含...
我相信它是在服务器启动时执行的,因为您的浏览器中有一个打开的页面,并且 Socket.IO 尝试重新连接每个n
秒。当服务器启动时,重新连接成功并且您的connection
处理程序触发(通常在客户端和服务器之间的连接成功建立时触发)。奇怪的是console.log
输出underfined
。我尝试了您的代码,对我来说,Socket.IO 0.9 和 1.0 都可以正常工作。你能展示你的完整代码吗,因为我认为问题出在其他地方。
你试过socket.io文件上传模块了吗?也许问题出在这个包上……我使用的是 socket.io 0.9。请看帖子更新。我添加了完整的客户端 - 服务器代码。我没有添加 HTML 部分。它只是通过单击要更改的图像打开的模式窗口。 <a title="Icon Actions" class="icon_actions" data-toggle="modal" href="#icon_action_modal" data-icon="<%= icon %>">
。 TY 为您提供帮助
【参考方案1】:
是的,有。
1) query
类似于GET
参数,因此将"param:value"
替换为"param=value"
(如果要传递多个参数,请按照通常使用URL 的方式进行操作:param=value&some_other_param=test
)
2) 在connection
处理程序中获取查询参数有一种更简单、更可靠(因为没有访问handshaken
对象的未定义属性的风险)的方法:
console.log(socket.handshake.query.param);
编辑:
在学习了您的完整代码后,我想我找出了导致问题的原因。问题是你可能误解了 Socket.IO 命名空间的主要思想。
我猜你在一页中有多个 Socket.IO 连接(io.connect
调用),对吧?通常一个连接就足够了。你的错误是你在鼠标事件上调用了io.connect
,但你应该在document.ready
上调用一次,然后只调用emit
ting。
看看下面的代码(客户端):
$(document).ready(function()
var socket = io.connect('', query: 'name=something');
// [...]
socket.on('some_event_from_server', function(data, cb) );
// [...]
$('#someButton').click(function()
socket.emit('markers_add', some: 'data'); //send `markers_add` message to server within main namespace
);
$('#someOtherButton').click(function()
socket.emit('icon_sets_add', some: 'thing', function(response)
//server may response to this request. see server side code below
);
);
);
服务器端代码:
io.on('connection', function(socket) //connection handler of main namespace
socket.on('markers_add', function(data) /* ... */ );
socket.on('icon_sets_add', function(data, cb)
// do something
cb(some: 'response');
);
// [...]
socket.emit('some_event_from_server', ); //server sends a message to a client
//BTW, now it should be OK:
console.log(socket.handshake.query.name);
);
如果您有一个命名空间,它应该可以工作。我实际上不知道这是 Socket.IO 的错误还是名称空间使用不当的结果,但是修改代码以仅创建一个名称空间应该可以解决问题。 所以在你的情况下,握手时根本不需要传递查询参数。实际上,如果你想让你的应用程序更安全,你必须使用查询参数。请参阅http://wlkns.co/node-js/socket-io-authentication-tutorial-server-and-client/(针对 Socket.io 0.9)
希望我的回答对你有所帮助。祝你好运!
【讨论】:
Ty 为您的回答 CuriousGuy。它没有解决我的问题,但 Ty 用于解释“查询”参数。我使用 socket.io file-upload 在我的网络服务器上上传一些图像。在“更新”情况下,我需要检索图像名称以将其分配到新图像上。在我的控制台中,我看到我的套接字上的连接是在我的图像更新操作之前。日志说,log input param : undefined
但此时,我还没有加载新图像......请看我的帖子更新。提前为您提供帮助
+1 ! Ty 为您的时间和您非常完整的答案。如果query
参数不起作用,您的解决方案是我的第二选择。我会朝那个方向走。 TY好奇的家伙!
@Curious:如何通过查询选项传递 2 个参数?提前致谢!
@Pritam 你试过这个:query: 'param1=something&param2=another'
吗?您可以像使用 URL GET 参数一样传递参数,即使用 &
作为分隔符
@span 是我的错误。 socket
是 'connection'
处理函数参数。编辑了我的答案。谢谢你:)【参考方案2】:
这就是我所做的。
客户
var socket = io.connect('http://localhost:8890', query: "foo=bar" );
服务器
io.on('connection', function (socket)
console.log(socket.handshake.query['foo']);
);
【讨论】:
这是完美的 应该是这样的。很棒(Y) 为什么这对我不起作用,你在这里使用的是什么版本的 socket.io? v4 你可以使用这个:var socket = io('http://localhost:8890', query: "foo=bar" );
【参考方案3】:
2021 年(socket.io 版本 4)
// client.js
const socket = io('https://195.174.3.104:3000', query: myParam: 'myValue' );
// server.js
io.on("connection", (socket) => console.log(socket.handshake.query.myParam); // myValue
来源:https://socket.io/docs/v4/client-initialization/#query
【讨论】:
socket.io/docs/v4/client-options/#query以上是关于socket.io / 连接参数的主要内容,如果未能解决你的问题,请参考以下文章
Socket.io node.js,如何避免记录连接时间或考虑页面刷新/多个套接字?