A group of stations is called a "P2P session." For the rest of this document, it is called a "session." The manager of a session is called the "session master." This terminal acts as the host for P2P communication. The terminals that participate in a session are called "stations." A terminal refers to itself as the "local station."
When using Internet communication, you must automatically select the ports for P2P communication and initialize the NAT traversal feature before initializing NetZ. For more information, see P2P Communications in Server Services.
The session master manages the information of the entire session, receives requests to join the session, manages the session clock that is synchronized in the session, and creates duplicated objects that are shared in the session. You can check whether a station is the session master by using Session::GetRole
.
The initial session master is the station that created the session by calling Session::CreateSession
. If this station leaves the session, the second station on the station list is chosen as the new session master.
The session master manages and can make changes to the session information. You can get session information for the local station using Session::GetLocalSessionDescription
. Session information is managed in the SessionDescription
class, and includes information such as the application title, the session name, the session ID, user-defined attributes, and the session's library version and build number.
A session is created by the session master using Session::CreateSession
.
The status of a session is controlled by the Session
class. This class is a singleton, meaning that it has only one instance, which has a global point of access. In other words, only one Session
may be created for each NetZ instance. The main function of the Session
class is to enable a session to be created and joined and also specific information about the session to be set and retrieved. After a station is part of a session, specific information about that station may be retrieved with the Station
class.
To create a session for local communication, the UDS network master must call Session::CreateSession
.
To join an existing session, call the Session::JoinSession
function using one of the following syntaxes.
Code 5.1 Joining a Session
qBool Session::JoinSession(CallContext* pCallContext,
const StationURL& refStationURL); // Asynchronous, for local communication.
qBool Session::JoinSession(const StationURL& refStationURL); // Synchronous, for local communication.
qBool Session::JoinSession(CallContext* pCallContext,
const qList< StationURL > & lstURLs); // Asynchronous, for Internet communication.
qBool Session::JoinSession(const qList< StationURL > & lstURLs); // Synchronous, for Internet communication.
In this code, refStationURL
and lstURLs
are references to the station URLs that are used to join sessions that you can get with nn::pia::local::UdsNetwork::GetMasterUrl
or MatchMakingClient::GetSessionURLs
. The URL list contains both the global and the local IP of the session being joined. The program will not run properly if you retrieve only one. If you use a member function for local communication during Internet communication, the application forcibly terminates on assert, or the Join
fails.
pCallContext
is a pointer to the CallContext
of the call. If defined, the call is made asynchronously. Otherwise it is made synchronously. If a call is synchronous, the system waits for the call to return a value or an error before performing the next task. If asynchronous, you may perform other tasks while waiting for the call to complete.
Before the Session::JoinSession
function terminates, all WellKnownDO
objects and all IDGenerator
core objects are guaranteed not only to be discovered but also to be discovered before any user duplicated objects. It is also guaranteed that UserDO
is not discovered inside the Session::JoinSession
function. The first UserDO
is only discovered when you call the Scheduler::Dispatch
function after calling the Session::JoinSession
function.
For more information about the threading model for Net-Z, see the section about the initialization settings for general features.
The only way to delete a Session
object is to delete the NetZ
instance. To leave a session, you must delete the NetZ
instance.
When the NetZ instance is destroyed, all duplicated objects, including those on the local station, are deleted.
To allow the joining of P2P sessions on a LAN, NetZ provides the LANSessionDiscovery
class. The LANSessionDiscovery
class can be used to search for P2P sessions that exist on the same LAN. This class can only be used on the session master and on terminals that are running on the same LAN. It cannot be used for non-debugging purposes and does not need to be configured when using local communication. When you call LANSessionDiscovery::Enable
, other sessions that were created on the LAN can be referenced using Session::QuerySession
.
Session::QuerySession
must be called before calling Session::CreateSession
or Session::JoinSession
.
For example, you could use the following code to search for P2P sessions on the LAN and output information from the session descriptions.
Code 5.2 Searching for P2P Sessions on LAN
LANSessionDiscovery::Enable();
.....
std::list<SessionDescription> lstResult;
if (Session::QuerySessions(&lstResult,false)==0)
{
QLOG(EventLog::Error, _T("No session found."));
}
else
{
std::list<SessionDescription>::iterator it=lstResult.begin();
while (it!=lstResult.end())
{
// Display relevant information from SessionDescription
QLOG(EventLog::Info, _T("Session ID : ") << it->GetSessionID());
}
}
As another example, the following code would search for P2P sessions on the LAN and join the first session in the list.
Code 5.3 Searching for and Joining P2P Sessions on LAN
LANSessionDiscovery::Enable();
.....
std::list<SessionDescription> lstResult;
if ( Session::QuerySessions(&lstResult,false) == 0 )
{
QLOG(EventLog::Error, _T("No session found."));
}
else
{
if (! Session::JoinSession(&lstResult.begin()) )
{
QLOG(EventLog::Error, _T("Join Failed."));
}
}
There are two kinds of stations: local stations that exist as long as the session exists, and peer stations that are generated upon searching and deleted upon leaving. A unique Station
object is generated for each one.
A Station
object includes information such as the station status, the DOHandle
, and the StationID
that is a unique global station identifier within the session. You can determine whether a Station
object is a local station or a peer station by using the Station::IsLocal
and Station::IsAPeer
member functions. You can also use Station::IsConnected
to check whether you can communicate with a different station.
Use Station::GetState
to get the current state of a station. Figure 5.1 shows the transitions between the different states: Station::Unknown
, Station::JoiningSession
, Station::CreatingSession
, Station::Participating
, Station::Leaving
, and Station::LeavingOnFault
.
Figure 5.1 Station State Transitions
You can use the following functions to know when stations join and leave the session.
API | Description |
---|---|
Station:: RegisterOperationBeginCallback() |
Sets a callback that is called when a station starts to join or starts to leave. |
Station:: RegisterOperationEndCallback() |
Sets a callback that is called when a station is finished joining or finished leaving. |
This section describes the main uses for these APIs.
Station::RegisterOperationBeginCallback
function is called.JoinStationOperation
(StationOperation::GetType
is Operation::JoinStation
) JoinStationOperation::GetTargetStation
function can get has not completed the process yet.DirectStream
can be received, and it can be stored in an internal NEX buffer and referenced, but we recommend referencing the received data after the join-in process has completed.LeaveStationOperation
(StationOperation::GetType
is Operation::LeaveStation
)LeaveStationOperation::GetLeavingStation
function, you can do so from this point in time.StationOperation
pOperation callback parameter with pOperation->GetTargetStation()
->GetState()
whether the reason for leaving was completed normally (Station::Leaving
) or by a fault (Station::LeavingOnFault
) process, such as a timeout.Station::RegisterOperationEndCallback
function is called.JoinStationOperation
(StationOperation::GetType
is Operation::JoinStation
)JoinStationOperation::GetTargetStation
function can get has already completed the join-in process. If you want to send application-specific data using DirectStream and RMC, you can do so from this point.LeaveStationOperation
(StationOperation::GetType
is Operation::LeaveStation
)To view sample code, see the AutoMatch
sample.
NEX uses keep-alive packets to monitor the existence of stations to detect the abnormal loss of stations (for example, due to network faults, peer stations powered off, or Wi-Fi turned off).
The library behaves in the following way to monitor the existence of stations.
StreamSettings::GetKeepAliveTimeout
function), keep-alive packets are sent to that station at intervals of StreamSettings::GetKeepAliveTimeout
. StreamSettings::GetMaxSilenceTime
function), it is assumed that the station is not connected.When loss of a station is detected, the state change can be detected with the callback registered by the Station::RegisterOperationBeginCallback
function and the Station::GetState
function because the lost station takes the value Station::LeavingOnFault
.
The NEX protocol statistical information can get the statistical operation object with the Station::GetEndPointInfoInterface
function. Get statistical information after communication starts or after executing the EndPointInfoInterface::ResetEndPointInfo
function with the EndPointInfoInterface::GetEndPointInfo
function. Refer to the EndPointInfo
structure for the available information. These statistics are the statistical information after duplicated object message handling with the BundlingPolicy
class and before packet handling with the StreamBundling
class settings. The data actually output might be grouped together by packet handling.
Get the packet count for the send buffer for reliable communication with the EndPointInfoInterface::GetReliableBufferPacketCount
or EndPointInfoInterface::GetReliableBufferPacketCounts
function.
Regarding RTT, use the Station::GetRTT
and Station::GetRTTAverage
functions to directly get the round trip delay for a specified message and the average round trip delay of messages sent between the local station and another station.
You can set the version of the application using the Station::SetLocalApplicationVersion
() function. The value set with this function can be obtained by using Station::GetApplicationVersion
.
In addition, a user-defined string can be associated with a particular station by using the Station::SetLocalIdentificationToken
function . One way to use an identification token is to use it to pass a password or other identifying tag when a station attempts to join a session to determine whether the station has the right to join the session. In this case, the information is passed to the connection point station so that that station can make a decision about the join request. The identification token is set on the joining station object, and is then accessible with the Station::GetIdentificationToken
function. An example of how to use an identification token is detailed in Chapter 13 Extended Duplicated Object Features.
CONFIDENTIAL