最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Node HTTP and WS server doesn't upgrade connection as expected - Stack Overflow

programmeradmin3浏览0评论

Edit: Overhauling the question and example, to try and narrow in on this. In local development I had avoided this issue by having ws and http each handled by their own server on their own port, and I'm running into some issues trying to get set on OpenShift, where I'm limited to a single port.

I'm trying to set up a simple Websocket based chat system using Node on OpenShift, and I'm clearly doing something wrong - I've set up a simple server which delivers my index page as expected, but when that page requests a Websocket connection, the server tries to answer it as a regular HTTP request instead of upgrading the connection as expected.

Live Version

Server:

var ip = process.env.OPENSHIFT_NODEJS_IP || '127.0.0.1';
var port = process.env.OPENSHIFT_NODEJS_PORT || 8080;

var ws = require( 'ws' ).Server;
var http = require( 'http' );
var path = require( 'path' );
var fs = require( 'fs' );

// Create main HTTP server for the application
var httpServer = http.createServer( function( request, response ){
	
	console.log( 'REQUEST: ' + request.url );
	
	var filename = path.join( process.cwd(), request.url );
	fs.exists( filename, function( exists ){
		fs.readFile( filename, 'binary', function( err, file ){
			
			if ( err ){
				console.log( 'FILE ERROR: ' + request.url );
				response.writeHead( 500, {"Content-Type": "text/plain"} );
				response.write( "500 - File Error\n" + err + "\n" );
				response.end();
				return;
			}
						
			response.writeHead( 200 );
			response.write( file, 'binary' );
			response.end();
				
		} );
	} );
	
} ).listen( port, ip, function(){
	
	console.log( 'Server is listening at http://' + ip + ':' + port );

} );

// Create WebSocket server and begin listening
wsServer = new ws( { server: httpServer } );
wsServer.on( 'connection', function( connection ){

	console.log( 'New websocket connection...' );
	connection.on( 'message', function( message ){
		connection.set( 'Received: ' + message );
	} );
	connection.send( 'wele!' );
	
});

Edit: Overhauling the question and example, to try and narrow in on this. In local development I had avoided this issue by having ws and http each handled by their own server on their own port, and I'm running into some issues trying to get set on OpenShift, where I'm limited to a single port.

I'm trying to set up a simple Websocket based chat system using Node on OpenShift, and I'm clearly doing something wrong - I've set up a simple server which delivers my index page as expected, but when that page requests a Websocket connection, the server tries to answer it as a regular HTTP request instead of upgrading the connection as expected.

Live Version

Server:

var ip = process.env.OPENSHIFT_NODEJS_IP || '127.0.0.1';
var port = process.env.OPENSHIFT_NODEJS_PORT || 8080;

var ws = require( 'ws' ).Server;
var http = require( 'http' );
var path = require( 'path' );
var fs = require( 'fs' );

// Create main HTTP server for the application
var httpServer = http.createServer( function( request, response ){
	
	console.log( 'REQUEST: ' + request.url );
	
	var filename = path.join( process.cwd(), request.url );
	fs.exists( filename, function( exists ){
		fs.readFile( filename, 'binary', function( err, file ){
			
			if ( err ){
				console.log( 'FILE ERROR: ' + request.url );
				response.writeHead( 500, {"Content-Type": "text/plain"} );
				response.write( "500 - File Error\n" + err + "\n" );
				response.end();
				return;
			}
						
			response.writeHead( 200 );
			response.write( file, 'binary' );
			response.end();
				
		} );
	} );
	
} ).listen( port, ip, function(){
	
	console.log( 'Server is listening at http://' + ip + ':' + port );

} );

// Create WebSocket server and begin listening
wsServer = new ws( { server: httpServer } );
wsServer.on( 'connection', function( connection ){

	console.log( 'New websocket connection...' );
	connection.on( 'message', function( message ){
		connection.set( 'Received: ' + message );
	} );
	connection.send( 'wele!' );
	
});

Client / Index Page:

<!DOCTYPE html>
<html>
	<head>
		<script>
		
			window.addEventListener( "load", function( event ){
				var socket = new WebSocket( 'ws://exalted-instanttabletop.rhcloud.');
			} );
			
		</script>
	</head>
	<body>
		<div id="log">Connecting...</div>
	</body>
</html>

Share Improve this question edited Feb 10, 2015 at 6:29 Dashiel N asked Feb 8, 2015 at 1:47 Dashiel NDashiel N 3192 silver badges13 bronze badges 3
  • 1 Do you understand that a webSocket connection starts as an HTTP request with some custom headers and then when both sides agree, the protocol is switched from HTTP to webSocket? So, you just need a handler looking at all the ining HTTP requests for the websocket upgrade header and then you can pass that socket off to your webSocket code. If you use socket.io in both client and server, it handles all this for you by just hooking into your http server to do just that. You don't create a separate webSocket server per se. – jfriend00 Commented Feb 8, 2015 at 7:07
  • 1 Yup. I understand in the general sense that that's how it should be done, but I've only found the one example I linked above, and it's not clear to me from that what I'm doing wrong - my initial ws:// request hits the standard response portion of my HTTP server, and what I'm trying to figure out is what I should be doing to let it upgrade properly. – Dashiel N Commented Feb 8, 2015 at 15:53
  • Updated the question pletely to clarify the issue that I'm having and give a simpler but more plete code example. – Dashiel N Commented Feb 10, 2015 at 6:28
Add a ment  | 

2 Answers 2

Reset to default 4

Here is a link to a very simple example application that uses the same Node.js server to accept and process both WS and HTTP connections. This should help get you started: https://github./openshift-quickstart/openshift-nodejs-http-and-websocket-example

var ipaddress = process.env.OPENSHIFT_NODEJS_IP || "127.0.0.1";
var port = process.env.OPENSHIFT_NODEJS_PORT || 8080;
var WebSocketServer = require('ws').Server
var http = require('http');

var server = http.createServer(function (request, response) {
    console.log((new Date()) + ' Received request for ' + request.url);
    response.writeHead(200, {'Content-Type': 'text/plain'});
    response.write("Wele to Node.js on OpenShift!\n\n");
    response.end("Thanks for visiting us! \n");
});

server.listen(port, ipaddress, function () {
    console.log((new Date()) + ' Server is listening on port 8080');
});

wss = new WebSocketServer({
    server: server,
    autoAcceptConnections: false
});

wss.on('connection', function (ws) {
    console.log("New connection");
    ws.on('message', function (message) {
        ws.send("Received: " + message);
    });
    ws.send('Wele!');
});

console.log("Listening to " + ipaddress + ":" + port + "...");

As it turns out, the issue I was having here was that Openshift has predefined that websocket connections must e in on port 8000, but are then forwarded to port 8080 on my gear, so my server needed to be listening on a different port than my client was explicitly connecting to, which is super counter-intuitive.

A mostly unrelated question I found on here ultimately lead me to an article from Openshift that lays out the details.

发布评论

评论列表(0)

  1. 暂无评论