我正在使用node.js构建一个基于浏览器的实时多人游戏。目前,我让客户端通过socket.io向游戏逻辑服务器发送用户输入,并将游戏世界的快照发送回客户端进行渲染。
以下是代码的简化版本。是否可以使用UDP将数据从基于浏览器的客户端发送到服务器,反之亦然?我知道Node.js有UDP module,但我不确定如何以这种方式实现它。
任何帮助将不胜感激。谢谢。
服务器:
var server = http.createServer(handler).listen(8888);
var iosocket = io.listen(server);
// request/response handler
function handler(req, res){
...
}
iosocket.sockets.on('connection', function(socket){
console.log("[x] Socket listener started");
socket.on('msg', function(data){
console.log( " [-] incoming message);
});
});
...
iosocket.sockets.emit("message", msg);
客户端:
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
<script type="text/javascript">
socket.on('connect', function(){
console.log("connected to server");
});
socket.on('message', function(message){
console.log('received message');
});
</script>
</head>
<body>
<canvas id='canvas' width="400" height="400">Canvas</canvas>
</body>
</html>
答案 0 :(得分:23)
通常,浏览器不支持UDP连接。特别是,有些浏览器可以。谷歌浏览器有一个套接字api:
http://developer.chrome.com/trunk/apps/socket.html
[2012/10/29编辑为socket不再是实验性的 - PhilH]
您也可以使用本机客户端接口中的套接字API(不确定,只能猜测)。
如果你想在不久的将来尝试在浏览器上做任何实时的事情,Websockets可能是你最好的选择,但那些只是TCP。
关于您对UDP与TCP速度的评论,UDP将始终更快。 TCP提供订购和交付保证(这意味着可能重试并保留其他数据包直到丢失的数据包最终到达其目的地),而UDP仅承诺发送一次,而不是关心事后发生的情况。 UDP只会发送一次数据包,你需要弄清楚它是否丢失了。当/如果您收到大量UDP数据包,如果订单很重要,您需要在数据有效负载中对此进行编码才能弄明白。
一般来说,UDP对于丢失少数通常无关紧要的数据包以及最新数据包真正重要的数据包非常有用。游戏通常可以使用TCP流,其中订购和保证交付很重要(重要的东西),UDP流用于对象移动等(其中只有最新位置真正重要,如果一个更新丢失,只要每个更新都无关紧要)包中包含完整位置[而不是所有包都很重要的增量]。
对于您自己的游戏,我建议首先在TCP上实现它,然后当您有更多经验时,您可以尝试将时间关键的东西(其中顺序和丢失的数据包更少)移动到单独的UDP流中。有许多项目失败了,因为人们首先开始使用UDP,然后尝试在其上进行订购和交付保证,有效地尝试重新实现TCP。这就是为什么以相反的方式做这件事更有意义。
答案 1 :(得分:1)
实时应用程序通常是接收至少30 Hz且抖动小于10%的数据更新的应用程序。 TCP / IP是可靠的,但不能以该速率发送定期更新,而偶尔不会出现抖动。这是因为TCP正在握手并确认可靠的传输,这阻碍了快速定期发送平滑更新的方式。 UDP是一种更简单的协议,其中套接字数据是火上浇油而忘记的。这本身就是一个问题,但这个问题比TCP / IP的抖动更容易克服。根据我的经验,UDP是唯一的前进方式,也是实时应用程序在诸如VoIP中使用的RTP之类的协议中使用它的原因。
Web套接字也是错误的希望,因为这是一个基于TCP的协议。我使用自定义UDP套接字,其中发送方和接收方保持序列号,并且可以告诉您数据包是丢失,重复还是不按顺序,WAN网络上的所有问题。找到使用UDP的方法并检测入站数据包以测量性能。
答案 2 :(得分:-4)
var server = require('http').createServer();
require('dgram-browserify').listen(server);
server.listen(8080);