• Peer to Peer Communication with PeerJS
  • Originally written by Dulanka Karunasena
  • Translation from: The Gold Project
  • This article is permalink: github.com/xitu/gold-m…
  • Translator: tong – h
  • Proofread by: jaredliw, CarlosChenN

Use PeerJS to easily achieve P2P communication

Implementing P2P communication is a challenging task, but it becomes much easier if you know how to use the right tools.

So in this article, I’ll look at PeerJS, a JavaScript library that encapsulates WebRTC to make P2P communication easier in Web applications.

How does PeerJS simplify WebRTC?

WebRTC is the standard used by many developers when it comes to real-time P2P communication in Web applications. But it also comes with some inherent complexity:

  • If you use pure WebRTC, First you define a Session Traversal Utilities for NAT (STUN) service that generates an ICE (Interactive Connectivity Establishment) protocol candidate for each node involved in the communication.
  • You then need to store the details of these ICE protocol candidates in your service.
  • Finally, you need WebSockets to handle real-time updates.

Even if you haven’t worked with WebRTC before, I’m sure you’ve already felt the complexity of implementing it. But don’t worry, PeerJS is here to save you.

With PeerJS, we don’t have to worry about STUN, ICE protocol candidates, or server creation, and we can even avoid using WebSockets.

PeerJS provides a complete, configurable API for peer-to-peer connections, as well as a service called PeerServer that makes it easy to establish connections between PeerJS clients.

So let’s see how we can use PeerJS to create a simple chat app.

Use PeerJS and React to set up your first chat room

Step 1 — Install PeerJS

First, we need to install PeerJS as a Node Module in your project and make the peer a global dependency.

// Install PeerJS NPM I PeerJS // Install Peer NPM i-g PeerCopy the code

Note: PeerJS is used to start PeerServer locally, but you can also use PeerServer Cloud instance.

Step 2 — Implement the chat room

Now, let’s move to the React app and initialize the chat component’s state first.

We will process our own ID, target node ID, chat message, and an instance of the Peer object within the state.

state = {
  myId: ' '.friendId: ' '.peer: {},
  message: ' '.messages: []}Copy the code

We need to create a Peer instance by defining the host name, port number, and path to manage our P2P connection. We will use this instance throughout the communication.

const peer = new Peer(' ', {
  host: 'localhost'.port: '3001'.path: '/'
});
Copy the code

Tip: You can use your own ID as the first argument, or leave it alone and let PeerServer generate a random ID. If you use const peer = new peer (); , you will connect to the PeerServer Cloud.

Peer instances have several methods to handle communication between peers. Peer-. on is used to listen for events on a node, which is useful when receiving calls from a remote node.

The open event will be issued after a successful connection to PeerServer. We will use this event to update myId and the state of the peer instance.

peer.on('open'.(id) = > {

this.setState({
    myId: id,
    peer: peer
   });
});
Copy the code

We then need to listen for the remote node connection through the Connection event and get the message sent by the remote node through its callback function.

peer.on('connection'.(conn) = > {
  conn.on('data'.(data) = > {

      this.setState({
        messages: [...this.state.messages, data]
      });

   });
});
Copy the code

We have now implemented the message receiving function. So in the final step, let’s create a method for message sending.

The peer. Connect method allows us to connect to a node by specifying the remote node ID. It then returns a DataConnection object to send messages to the node.

send = () = > {
  const conn = this.state.peer.connect(this.state.friendId);

  conn.on('open'.() = > {

    const msgObj = {
      sender: this.state.myId,
      message: this.state.message
    };

   conn.send(msgObj);

    this.setState({
      messages: [...this.state.messages, msgObj],
      message: ' '
    });

  });
}
Copy the code

Step 3 — Implement video chat

Now, let’s modify the chat room for sending video messages. The implementation of this functionality is very similar to the steps we discussed earlier. We can listen for a call event from a remote node by using the peer-. on method. The listener event provides a callback function that carries the MediaConnection object, and the receiver’s video and audio streams are provided to the Answer method of the MediaConnection object.

peer.on('call'.(call) = > {

var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;

getUserMedia({ video: true.audio: true }, (stream) = > {

  this.myVideo.srcObject = stream;
  this.myVideo.play();
  
  call.answer(stream);

  call.on('stream'.(remoteStream) = > {
    this.friendVideo.srcObject = remoteStream;
    this.friendVideo.play();
  });

}, err= > { console.log('Error! ')}); });Copy the code

Now, let’s send a video call from our port to the remote node. This method is similar to an incoming call response. We need to call the call method on the original peer instance and provide the node ID and the video stream as its parameters.

The call method will thus return a MediaConnection object through which we can use the video stream of the node.

videoCall = () = > {

var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;

getUserMedia({ video: true.audio: true }, (stream) = > {

  this.myVideo.srcObject = stream;
  this.myVideo.play();

  const call = this.state.peer.call(this.state.friendId, stream);

  call.on('stream'.(remoteStream) = > {
    this.friendVideo.srcObject = remoteStream;
    this.friendVideo.play();
  });
}, err= > { console.log('Error! ')}); }Copy the code

Step 4 – The final item

Finally, it’s time to add some JSX to our chat room. Let’s add two input boxes to enter the node ID and chat message. We will use the ref attribute to manipulate the video element.

return (
<div className="wrapper">
  <div className="col">
    <h1>My ID: {this.state.myId}</h1>

    <label>Friend ID:</label>
    <input
     type="text"
     value={this.state.friendId}
     onChange={e= >{ this.setState({ friendId: e.target.value }); }} / ><br />
<br />

    <label>Message:</label>
    <input
     type="text"
     value={this.state.message}
     onChange={e= >{ this.setState({ message: e.target.value }); }} / ><button onClick={this.send}>Send</button>
    <button onClick={this.videoCall}>Video Call</button>
    {
      this.state.messages.map((message, i) => {
        return (
          <div key={i}>
          <h3>{message.sender}:</h3>
          <p>{message.message}</p>
          </div>)}); }</div>
    <div className="col">
      <div>
        <video ref={ref= > this.myVideo = ref} />
      </div>
      <div>
        <video ref={ref= > this.friendVideo = ref} />
      </div>
    </div>
  </div>
  );
Copy the code

In this way! Now a quick video chat is all set up. The final result looks something like this, and you can find the full code in my GitHub repository.

Note: Some browsers (especially mobile browsers) may not allow the use of the camera and microphone when the connection is not HTTPS. You can follow the steps in this article to set up a local HTTPS connection.

conclusion

WebRTC is a browser standard that supports P2P communication. But with STUN servers, ICE protocol candidates, SDPs, and WebSockets involved, implementing WebRTC is a little more complicated.

PeerJS simplifies the process by encapsulating WebRTC, giving us simpler events and methods.

So, I invite you to try using PeerJS and let me know what you think in the comments section.

Thanks for reading!!

If you find any errors in the translation or other areas that need improvement, you are welcome to revise and PR the translation in the Gold Translation program, and you can also get corresponding bonus points. The permanent link to this article at the beginning of this article is the MarkDown link to this article on GitHub.


Diggings translation project is a community for translating quality Internet technical articles from diggings English sharing articles. The content covers the fields of Android, iOS, front end, back end, blockchain, products, design, artificial intelligence and so on. For more high-quality translations, please keep paying attention to The Translation Project, official weibo and zhihu column.