javascript 用于实时多人游戏的 Node.js UDP
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11413364/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Node.js UDP for realtime multi-player game
提问by RobotEyes
I am building a real-time multi-player browser-based game using node.js. At the moment I have the client send user input to the game logic server via socket.io and a snapshot of the game world sent back to the client for rendering.
我正在使用 node.js 构建一个基于浏览器的实时多人游戏。目前,我让客户端通过 socket.io 将用户输入发送到游戏逻辑服务器,并将游戏世界的快照发送回客户端进行渲染。
Below is a simplified version of the code. Is it possible to use UDP to send data from the browser-based client to the server and vice-versa? I know Node.js has a UDP modulebut I am unsure how to implement it in this way.
下面是代码的简化版本。是否可以使用 UDP 将数据从基于浏览器的客户端发送到服务器,反之亦然?我知道 Node.js 有一个UDP 模块,但我不确定如何以这种方式实现它。
Any help would be appreciated. Thank you.
任何帮助,将不胜感激。谢谢你。
Server:
服务器:
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);
Client:
客户:
<!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>
回答by Marius Kjeldahl
Generally, browsers do not support UDP connections. Specifically, some browsers do. Google Chrome has a socket api:
通常,浏览器不支持 UDP 连接。具体来说,一些浏览器可以。谷歌浏览器有一个套接字 api:
http://developer.chrome.com/trunk/apps/socket.html
http://developer.chrome.com/trunk/apps/socket.html
[2012/10/29 Edited as socket is no longer experimental - PhilH]
[2012/10/29 编辑为 socket 不再是实验性的 - PhilH]
You could possibly also use socket APIs from the native client interfaces as well (not sure, only guessing).
您也可以使用来自本机客户端接口的套接字 API(不确定,只是猜测)。
If you're going try to do anything real-time on browsers in the near future, Websockets is probably your best bet, but those are TCP only.
如果您打算在不久的将来尝试在浏览器上实时执行任何操作,那么 Websockets 可能是您最好的选择,但这些仅适用于 TCP。
Regarding your comments on UDP versus TCP speed, UDP will always be faster. TCP offers ordering and delivery guarantees (this means possible retries and holding other packets back until a lost packet finally arrives at its destination), while UDP only promises to send it once, not caring what happens with it afterwards. UDP will only send it's packet once and you need to figure out whether it got lost. When/if you receive lots of UDP packets, if order matters, you need to encode this in your data payload to be able to figure it out.
关于您对 UDP 与 TCP 速度的评论,UDP 总是更快。TCP 提供排序和交付保证(这意味着可能重试并阻止其他数据包直到丢失的数据包最终到达其目的地),而 UDP 只承诺发送一次,而不关心之后会发生什么。UDP 只会发送它的数据包一次,您需要弄清楚它是否丢失了。当/如果您收到大量 UDP 数据包,如果顺序很重要,您需要将其编码到您的数据有效负载中以便能够弄清楚。
In general, UDP will be great for packets where missing a few usually do not matter and where only the latest packet really matters. A game may typically use a TCP stream where ordering and guaranteed delivery matters (the important stuff), and UDP streams for object movements etc (where only the latest position really matters, and if one update got lost it does not matter as long as each package contain the full position [instead of a delta where all packets matter]).
一般来说,UDP 非常适合丢失一些通常无关紧要的数据包,并且只有最新的数据包才真正重要。游戏通常可能使用 TCP 流,其中排序和保证交付很重要(重要的东西),以及 UDP 流用于对象移动等(其中只有最新的位置才是真正重要的,如果一个更新丢失了,只要每个更新都无关紧要)包包含完整位置[而不是所有包都很重要的增量])。
For your own game, I suggest implementing it on TCP first, and then when you have some more experience, you can try move the time critical stuff (where order and lost packets matter less) into separate UDP streams. There are many projects that have failed because people started with UDP first, and then tried bolting on ordering and delivery guarantees on top of it, effectively trying to reimplement TCP. Which is why doing it the other way around makes more sense.
对于你自己的游戏,我建议先在 TCP 上实现它,然后当你有更多的经验时,你可以尝试将时间关键的东西(顺序和丢失的数据包不太重要)移动到单独的 UDP 流中。有很多项目都失败了,因为人们首先从 UDP 开始,然后尝试在其上附加订购和交付保证,有效地尝试重新实现 TCP。这就是为什么反过来做更有意义的原因。
回答by lvcsim
A realtime application is generally one that receives data updates of at least 30 Hz and with less than 10% jitter. TCP/IP is reliable but can't send periodic updates at that rate without jitter going off the scale occasionally. This is because TCP is handshaking and acknowledging to ensure reliable transmission which gets in the way of sending fast periodically smooth updates. UDP is a simpler protocol where the socket data is fire and forget. This is itself a problem but that problem is easier to overcome than the poor jitter of TCP/IP. In my experience UDP is the only way forward and why real-time applications use it inside protocols such as RTP used in VoIP.
实时应用程序通常是接收至少 30 Hz 的数据更新且抖动小于 10% 的应用程序。TCP/IP 是可靠的,但不能以该速率发送定期更新而不会偶尔出现超出规模的抖动。这是因为 TCP 正在握手和确认以确保可靠的传输,这阻碍了发送快速定期平滑更新。UDP 是一种更简单的协议,其中的套接字数据是“即发即忘”。这本身就是一个问题,但与 TCP/IP 的不良抖动相比,该问题更容易克服。根据我的经验,UDP 是唯一的前进方式,也是实时应用程序在 VoIP 中使用的 RTP 等协议中使用它的原因。
Web Sockets are false hope as well since that is a TCP-based protocol. I use custom UDP sockets where the sender and receiver maintain a sequence number and that can tell you if packets are lost, duplicated or out of sequence, all problems on WAN networks. Find ways to use UDP and instrument the inbound data packets to measure performance.
Web Sockets 也是错误的希望,因为它是基于 TCP 的协议。我使用自定义 UDP 套接字,其中发送方和接收方维护一个序列号,它可以告诉您数据包是否丢失、重复或乱序,以及 WAN 网络上的所有问题。寻找使用 UDP 和检测入站数据包的方法来衡量性能。
回答by stackoverflowaccount
var server = require('http').createServer();
require('dgram-browserify').listen(server);
server.listen(8080);