Advertisement

WebRTC for peer to peer multiplayer?

Started by September 22, 2014 05:18 PM
8 comments, last by langorn 10 years, 2 months ago
Hello!

I've gotten interested in making multiplayer games using HTML5. I've looked into WebSockets via socket.io, but I was disappointed that all the communication seemed to have to go through the server. What I had been hoping for was to use the web server only as a kind of matchmaker and resource deliverer, and let the clients send the game state updates between each other (with the client that created the game acting as the game server). Without this kind of direct communication between the clients, it seems like the web server would get an unproportionate workload, especially with a couple of games running.

I found that WebRTC could be used for peer to peer communication in browsers, but I haven't found much information on the subject. Has anyone used this for a game yet? Is there any proper documentation available? How realistic is it to implement peer-to-peer communication via the browser at the current date? :)

I would love to hear the experiences of anyone else who has been developing multiplayer games for the web and what the common solutions are, if any.
I've been waiting for someone to try this. I believe it "can" be done, but only for the "right kind" of game. An Unreal Tournament or Counter-Strike player would probably be unhappy with the performance. A Starcraft or World of Warcraft player might think it's fine.

Of course, you get all the other problems of peer-to-peer, too: How to match up players, how to prevent cheating, etc.
enum Bool { True, False, FileNotFound };
Advertisement
My plan is to make a co-op platformer/action game for a small group of people, so the cheating aspect is hopefully not too relevant in this case, even though I think it is possible to solve if one of the clients are acting server.

My current idea is to use the server as a broker of kind. Let one of the clients (the host) create the game via a web form. The server will generate a random hash and send it back in the URL of the response. The host can send the URL to any player they wish to invite. A peer that connects with the URL will be matched by the server with the host that is associated with the given hash. The server will respond with the connection details to the host, and the peer can connect to the host.

It /feels/ straightforward and I'm going to experiment with it, but I'm not sure if I'm on the right path here.

I'm mostly looking to alleviate the web server of having to mirror all the game messages and instead only focusing on the whole setting up the connections. The latency of the game itself will be another challenge :D
Have you read articles lik http://chimera.labs.oreilly.com/books/1230000000545/ch18.html#_signaling_and_session_negotiation (very detailed but extremely valuable - read it thoroughly, don't just skim it) or http://www.html5rocks.com/en/tutorials/webrtc/datachannels/ ?

In particular see the RTCPeerConnection.createDataChannel method. You have to do all the other usual work of actually making the connection (using a server to negotiate the connection and deal with NAT) but then you can create multiple channels with the settings you want (in-order/out-of-order, reliable/unreliable/partially-reliable) and use those to send binary or text messages pretty much identically to WebSocket.

Note that WebRTC is always encrypted so you don't have to add any additional encryption (however, _proof of identity_ is still left up to you!). WebRTC does not compress data so you're still on your own if you want to minimize bandwidth usage and your data stream is compression-friendly (the usual audio/video usage of WebRTC does not usually lend itself well to compression since those streams are already compressed, of course). WebRTC has its own message header overhead, plus the header overhead of SCTP, which is tunneled over UDP so there's also that header overhead, so ultimately each packet is a bit fatter than it would be with a hand-rolled UDP protocol; that's not a major issue but it's something you have to keep in mind.

Nothing stops you from using WebRTC to communicate over UDP to a central server rather than purely peer-to-peer. The protocol and API doesn't make it straight forward but nothing stops it from being used that way. You go through all the usual signaling and connection stuff but have it connect the browser to a central server (or one of a cluster of central servers) rather than another player. Then your server can use all the benefits of WebRTC's connection model to communicate which each user. That first link above mentions it but doesn't provide any direct examples.

Sean Middleditch – Game Systems Engineer – Join my team!

Great info and links, Sean! I'll definitely have a read through them, it is more information than I've found previously and it's nice to get something substantial on the subject. I'm considering using WebSockets or something for the connection to the central web server, since it is already suitable for that purpose. WebRTC is the option I'm considering between the browsers when game state data needs to be distributed. I'll read up on the protocol and see what it can offer though, and try out some implementations and see what works and what doesn't.
So I just spent some time researching this further since I've been pointing people at WebRTC for games stuff lately and... man, it's complicated.

It _should_ and _can_ be easy, but there just aren't many drop-in libraries ready to use for this stuff. There's the massively over-complicated C++ WebRTC library from Google that handles all the audio/video crap you don't need. There's node-wrtc that wraps that up for Node. You have to use the ICE server stuff to setup a connection even to a well-known "peer" server... I think.

In short, this is a problem space just begging for an industrious person to come along and make a super simple permissively-licensed C library (easy to wrap in C++, Go, Node/JS, Python, etc.) for the server and a nice DataChannel-only client for the Web. Preferably supporting fallback to WebSockets for clients without WebRTC support.

All totally feasible, just not yet plug-and-play. smile.png

Sean Middleditch – Game Systems Engineer – Join my team!

Advertisement
For games, there exists a plug-and-play library: RakNet. It's now open source.

For web browsers, the problem is that "web developers" don't think like "installed application developers," and additionally, "telecom developers" don't think like "game developers."
enum Bool { True, False, FileNotFound };
i am currently developing a looking for group website , just using the peerjs to making a prototype of this webrtc . it's quite easy
here is the code . you can go to my website to try this.
open 2 webpage
http://www.raidboss.net/chat/ ( find the token and paste in the second url )
http://www.raidboss.net/call/opf26urtbbne9udi (paste at here , replace this opf26urtbbne9udi)
description:
User A owns a phone , User B want to call User A , so he need User A's Phone number(or you can call it token);
You need to create 2 pages for user A , user B ,
the user scenario is user B call user A through the phone number(token);
User A's code

<html>
<head>
<script src="http://cdn.peerjs.com/0.3/peer.js"></script>
</head>


<body>
<div id="userId">opf26urtbbne9udi</div>
<!-- this is user A 's phone number -->
<video autoplay=""></video>
<script>
        var peer = new Peer({key: 'xxxxxxxxx'});
        <!-- this is the peerjs id , u need to get your own one -->


        peer.on('open', function(id) {
          console.log('My peer ID is: ' + id);
          $('#userId').html(id);
          <!-- it can show your token -->
        });
        peer.on('connection', function(conn) {
          conn.on('data', function(data){
            // Will print 'hi!'
            console.log(data);
          });
        });






        navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
        peer.on('call', function(call) {
          navigator.getUserMedia({video: true, audio: true}, function(stream) {
            call.answer(stream); // Answer the call with an A/V stream.
            call.on('stream', function(remoteStream) {
              // Show stream in some video/canvas element.
                var video = document.querySelector('video');
                video.src = window.URL.createObjectURL(remoteStream);
            });
          }, function(err) {
            console.log('Failed to get local stream' ,err);
          });
        });




</script>
</body>
</html>
user B's code

<div id="userId"></div>
<div>
  <input type="text" id="callToWho">
  <div id="calling">Calling</div>
</div>


<video autoplay></video>


<script>
    var peer = new Peer({key: 'uts8vpuag1213daii'});  <!--this is the user token need register from peerjs -->


    var uid = '';
    peer.on('open', function(id) {
      console.log('My peer ID is: ' + id);
      uid = id;
    });
    var conn = peer.connect(uid);
    conn.on('open', function(){
      conn.send('hi!');
    });


    conn.on('data', function(data) {
      console.log('Received', data);
    });




    var toUser = {{token}} //'opf26urtbbne9udi';
    <!-- i am using python django to generate the token through the url get  , if you dont want to using any server side language , then you can just simply copy the user A 's token and place (var toUser = opf26urtbbne9udi)    -->

    callTo(toUser);
    function callTo(toUser){


      navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
      navigator.getUserMedia({video: true, audio: true}, function(stream) {
        var call = peer.call(toUser, stream);
        call.on('stream', function(remoteStream) {
          // Show stream in some video/canvas element.
              var video = document.querySelector('video');
              video.src = window.URL.createObjectURL(remoteStream);
        });
      }, function(err) {
        console.log('Failed to get local stream' ,err);
      });
    }
</script>

one more thing need to mention , it's just using for 1 vs 1 communication ,

multi people chatroom i still try figure out how to do it

Note that the PeerJS people charge for their server service, once you go over 50 matchmade sessions at a time.
That may be totally fine for you -- trading a little money for a lot of saved time is often actually the smart thing to do.
enum Bool { True, False, FileNotFound };

yup , but u can host a turn server by yourself ( i haven't read through the tutorial). that's the way you dont need to pay.

in the long term , i think i will use google hangout , if it can support multi user chat .

This topic is closed to new replies.

Advertisement