ESFramework development manual (04)-reliable P2P

Source: Internet
Author: User
Document directory
  • TCP punching

This article introduces ESFramework development manual (00)-the last of the four major weapons mentioned in the article: P2P channels.

Compared with 1.x, ESPlus 2.0 provides P2P support.

ESPlus 2.0 provides P2P Channels Based on TCP and UDP (not only supports LAN, but also P2P communication over WAN). Whether we use TCP-based P2P channels, we still use UDP-Based P2P channels. ESPlus ensures that all P2P communication is reliable. This is because ESPlus re-encapsulates the TCP mechanism based on the original UDP to make UDP as reliable as TCP. In distributed systems (such as IM systems) that require high-frequency communication between clients, reliable P2P communication will save you huge bandwidth and server costs.

1. P2P penetration

Anyone who knows about P2P knows that the establishment of P2P channels needs to be completed through "hitting holes", and whether the P2P hitting between client instances on the PC after two NAT devices can be successful, or, whether a P2P channel can be successfully established depends on the type of NAT device.

UDP punching

Most of our commonly used NAT devices, such as routers and firewalls, are Cone (Full Cone, Restricted Cone, and Port Restricted Cone, therefore, the success rate of UDP holes is still very large (for example, over 80% ).
The relationship between UDP-Based P2P penetration success rate and NAT device types is as follows:

From the list, we can see that the most troublesome problem is the distributed Ric type. If either party needs P2P communication is the distributed Ric type, port prediction technology is required for punching holes, and the success hopes of punching holes are very slim.
You can download a NAT detection program (such as STUN) from the Internet to check the types of NAT devices such as your own vro, to determine whether the UDP-Based P2P channel can be successfully created.

TCP punching

The principle of TCP holes is almost the same as that of UDP holes. Unfortunately, few NAT devices currently support TCP holes, so that there is little chance of successfully establishing a TCP-based P2P connection between client instances located behind two NAT instances. We hope that in the near future, the number of NAT devices supporting TCP holes will gradually increase, which takes time. For more information about TCP-based P2P, see here.
Even so, it is necessary for ESFramework to support TCP-based P2P, because in the following two cases, the TCP-based P2P channel can be successfully created.

  • Both parties are located in the same intranet.
  • At least one of the communications parties runs on a machine with a public IP address.

In both cases, no TCP holes are required, and no additional support from the NAT device is required. The TCP-based P2P channel can be successfully established.

2. Reliability of P2P Channels

Since our P2P channel may be TCP-based or UDP-based, the P2P channel inherits the features of the Protocol: TCP-based P2P channels are reliable, whereas UDP-Based P2P channels are unreliable.

Fortunately, ESFramework/ESPlus uses enhanced UDP internally-simulates the TCP mechanism based on UDP to ensure the reliability of communication. Therefore, ESPlus provides reliable P2P channels.

ESPlus also provides an option to use the original UDP. You only need to set the ReliableUdpEnabled attribute of IRapidPassiveEngine to false. In this way, the ESPlus UDP-Based P2P channel is unreliable.

3. Select a channel

When introducing the CustomizeInfo space, we mentioned that you can use ICustomizeOutter to send a P2P message to another online user. The following methods of this interface send P2P messages:

Public interface ICustomizeOutter: IOutter
{Void Send (string targetUserID, int informationType, byte [] info );

Void SendCertainly (string targetUserID, int informationType, byte [] info );

Byte [] Query (string targetUserID, int informationType, byte [] info );

/// <Summary>
/// Send information to the online user targetUserID through the P2P channel (even unreliable.
/// </Summary>
/// <Param name = "targetUserID"> Target User ID for receiving messages </param>
/// <Param name = "informationType"> Custom information type </param>
/// <Param name = "info"> Information </param>
/// <Param name = "actionType"> action taken when the P2P channel does not exist </param>
Void SendByP2PChannel (string targetUserID, int informationType, byte [] info, ActionTypeOnNoP2PChannel actionType );
}

In addition to the SendByP2PChannel method, other methods use reliable channels to send P2P messages. If a reliable P2P channel exists (for example, (TCP-based P2P channel or enhanced UDP-Based P2P channel), it is sent through the P2P channel, otherwise it is still transmitted through the server.

When a P2P channel exists with the target user, the SendByP2PChannel method must use a P2P channel to send messages even if it is unreliable (for example, a normal UDP-Based P2P channel. Therefore, calling the SendByP2PChannel method to send the Target message means that the target message can be discarded. If the P2P channel does not exist with the target user, the operation will depend on the value of ActionTypeOnNoP2PChannel, which is the 4th parameter of the method, either through the server or by discarding the message.
ActionTypeOnNoP2PChannel is defined as follows:

Public enum ActionTypeOnNoP2PChannel
{
/// <Summary>
/// Transfer through the server
/// </Summary>
TransferByServer = 0,

/// <Summary>
/// Discard the message
/// </Summary>
Discard
} There may be two P2P channels between the two clients: one is TCP and the other is UDP. In this case, ESFramework will give priority to TCP-based P2P channels.

Remember the TransferByServer method of the ICustomizeOutter interface we introduced earlier. It means that even if a reliable P2P channel exists, the information must be transmitted through the server.

By the way, when we use the IFileOutter introduced earlier to send files to other online users, ESFramework uses a reliable channel at the underlying layer to avoid packet loss or disorder.

4. P2P channel controller IP2PController

ESPlus provides the ESPlus. Application. P2PSession. Passive. IP2PController interface for the client to control and manage P2P channels.

The P2PController attribute is exposed through RapidPassiveEngine. We can obtain the reference of IP2PController.

The IP2PController interface is defined as follows:

Public interface IP2PController
{
/// <Summary>
/// This event is triggered when a P2P connection attempt fails. The parameter is the UserID of the other party.
/// </Summary>
Event CbGeneric <string> P2PConnectFailed;


/// <Summary>
/// This event is triggered when a P2P Channel is successfully created.
/// </Summary>
Event CbGeneric <P2PChannelState> P2PChannelOpened;


/// <Summary>
/// This event is triggered when a P2P Channel is disabled. The parameter is the UserID of the other party.
/// </Summary>
Event CbGeneric <P2PChannelState> P2PChannelClosed;


/// <Summary>
/// Whether to Enable PMTU automatic discovery when using reliable UDP P2P channels. The default status is disabled.
/// </Summary>
Bool PMTUDiscoveryEnabled {get; set ;}


/// <Summary>
/// The type of the P2P channel used. The default value is TcpAndUdp, indicating both TCP and UDP holes are attempted.
/// </Summary>
P2PChannelMode P2PChannelMode {get; set ;}


/// <Summary>
/// Try to establish a P2P Channel with the target user. (Asynchronous mode .)
/// </Summary>
/// <Param name = "destUserID"> UserID of the target user </param>
Void P2PConnectAsyn (string destUserID );


/// <Summary>
/// Whether a P2P channel exists with the target user.
/// </Summary>
Bool IsP2PChannelExist (string destUserID );


/// <Summary>
/// Whether the P2P channel is busy. If the return value is null, it indicates that there is no P2P channel, or you do not know the busy status of the P2P channel (when the tcp channel is connected or the Unreinforced UDP channel is used ).
/// </Summary>
Bool? P2PChannelIsBusy (string destUserID );


/// <Summary>
/// Obtain the status of all P2P channels.
/// </Summary>
Dictionary <string, P2PChannelState> GetP2PChannelState ();


/// <Summary>
/// Obtain the P2P channel status of the target user.
/// </Summary>
P2PChannelState GetP2PChannelState (string destUserID );

}

/// <Summary>
/// P2P channel model.
/// </Summary>
Public enum P2PChannelMode
{
TcpAndUdp = 0,
Tcp,
Udp
}

First, we can set the P2PChannelMode attribute to require ESPlus to try UDP or TCP when trying to create a P2P channel.

Before we talk to a P2P user, we can call the P2PConnectAsyn method of IP2PController, this method will try to establish a P2P connection with the target user in the background thread (namely, UDP and TCP holes ). When a P2P connection is established successfully, the P2PChannelOpened event is triggered, and subsequent P2P messages can be sent through the P2P channel. If a P2P connection fails, the P2PConnectFailed event is triggered.

Each P2P channel corresponds to a P2PChannelState instance in the memory. This instance records the information and real-time status of the P2P channel, such as the UserID and address information of the Peer peer to a P2P session, the protocol type of the P2P channel, the channel creation time, the number of messages sent through the channel, the last message sending time, and whether the current channel is reliable. The class diagram of P2PChannelState is as follows:


When the established P2P channel is closed (it may be because the peer is offline, the P2P connection is interrupted, or the UDP P2P heartbeat times out), IP2PController triggers the P2PChannelClosed event.
At any time, we can use the IsP2PChannelExist method of IP2PController to query whether a P2P channel exists with the target user. We can also use the GetP2PChannelState method to obtain the real-time status of all or a specific P2P channel.

5. Summary of four weapons

So far, all the four weapons have been introduced. Now we will sort out the APIs and callback interfaces involved in the four weapons in the form of a table.


The API is implemented by the framework for us. For example, we can directly use all components ending with Outter and Controller. All the interfaces ending with Handler are implemented in the program according to the specific needs of the project. These implemented classes are injected into the framework, for the framework callback (passed through the corresponding parameters of the Initialize method of the client and server Rapid engine)-in this way, the framework can drive the entire business process to run.

Finally, you can view the source code of the P2P demo (ESFramework Demo-P2P communication Demo (with the source code) and run the demo to try P2P. Thank you.

 

Read more ESFramework development manual articles.

Certificate -----------------------------------------------------------------------------------------------------------------------------------------------

Download the free version of ESFramework and demo source code

 

For any questions about ESFramework, please contact us:

Tel: 027-87638960

Q: 372841921

Mail: esframework@oraycn.com

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.