我正在使用Express在Node.js中开发一个Web服务器,我想特别使用Socket.io作为WebSockets。但是,托管我的应用程序的服务器环境是IIS,并且无法更改。 IIS版本足够高,启用了WebSockets,并安装了iisnode v0.2.21。 Express正常工作,提供我的页面和内容,但WebSockets没有。相反,websocket连接以HTTP 200状态而不是预期的HTTP 101重复终止,从而阻止WebSockets工作。我已经为我想到的IIS_IUSRS组设置了权限。
有时我会收到一个错误页面,其中包含以下文字:
HRESULT: 0x6d
HTTP status: 500
HTTP subStatus: 1013
HTTP reason: Internal Server Error
我还没有尝试使用SSL或Secure WebSockets,因此我在StackOverflow上找到的其他解决方案似乎不适用。
我在客户端遇到这样的错误:
polling-xhr.js:264 POST http://my-website/socket.io/?EIO=3&transport=polling&t=LnMfjZr&sid=LQjLpiGwsN3K-gNPAAAA 500 (Internal Server Error)
polling-xhr.js:264 POST http://my-website/socket.io/?EIO=3&transport=polling&t=LnMfjaC&sid=LQjLpiGwsN3K-gNPAAAA 500 (Internal Server Error)
websocket.js:112 WebSocket connection to 'ws://my-website/socket.io/?EIO=3&transport=websocket&sid=P8q_HoyfgJb0F75rAAAA' failed: Error during WebSocket handshake: Unexpected response code: 200
polling-xhr.js:264 POST http://my-website/socket.io/?EIO=3&transport=polling&t=LnMfkAb&sid=P8q_HoyfgJb0F75rAAAA 500 (Internal Server Error)
我按照了web.config
找到的所有说明:
<system.webServer>
<!--so that IIS websockets don't interfere with Node websockets-->
<webSocket enabled="false" />
<!-- indicates that the hello.js file is a node.js application
to be handled by the iisnode module -->
<httpErrors existingReponse="PassThrough"></httpErrors>
<handlers>
<add name="iisnode" path="app.js" verb="*" modules="iisnode" />
</handlers>
<modules runAllManagedModulesForAllRequests="false"/>
<rewrite>
<rules>
<!-- Don't interfere with requests for node-inspector debugging -->
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url=".+\.js\/debug[\/]?"/>
</rule>
<!-- All other URLs are mapped to the Node.js application entry point -->
<rule name="DynamicContent">
<match url="/*"/>
<action type="Rewrite" url="app.js"/>
</rule>
</rules>
</rewrite>
<directoryBrowse enabled="false"/>
<!-- exclude node_modules directory and subdirectories from serving
by IIS since these are implementation details of node.js applications -->
<security>
<requestFiltering>
<hiddenSegments>
<!--<add segment="bin" />-->
</hiddenSegments>
</requestFiltering>
</security>
</system.webServer>
</configuration>
这是app.js
:
'use strict';
var debug = require('debug');
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var app = express();
var server = require('http').Server(app);
var routes = require('./routes/index');
var users = require('./routes/users');
var api = require('./routes/api')(server);
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
app.use('/api', api);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function (err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function (err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
app.set('port', process.env.PORT || 3000);
server.listen(app.get('port'), function () {
debug('Express server listening on port ' + server.address().port);
});
和api.js
,它实际上设置了Socket.IO服务器:
module.exports = function (server)
{
var socketio = sio(server);
var router = express.Router();
var game = new model.Game();
socketio.on("connection", (socket) =>
{
console.log(`houston we have socket ${socket.id}`);
try
{
socket.on('message', function (data)
{
console.log(`message: ${JSON.stringify(data)}`);
// my code here
});
socket.on("disconnect", (socket) =>
{
socketio.send("player.disconnected", { id: player.id });
// my code here
});
}
catch (err)
{
// I put a breakpoint here, we never end up here
}
// debugger always makes it to the end of this function
});
}
当我使用调试器逐步执行此代码时,似乎执行使其到达连接处理程序的末尾,然后服务器立即重新启动。 我做错了什么,为什么套接字被发送200响应?
我知道错误页面被编码为200个响应,但由于它们被发送到WebSocket连接,因此Chrome不允许我检查它们,而只是向我显示“(操作码-1)”。使用Fiddler检查WebSocket连接的尝试表明它确实是上面描述的错误页面,HRESULT为0x6d。