Use ReliableBroadcastProtocol to send relatively large amounts of data to multiple stations. With guaranteed delivery, any station can send data regardless of whether the station is the session host or client.
This allows you to efficiently send data to multiple stations at one time—particularly when using local communication networks on the CTR because data can be sent and received using the broadcast feature in the UDS library.
The basic process flow when using ReliableBroadcastProtocol is as follows.
Each item is described in more detail below.
The following code sample shows the initialization of ReliableBroadcastProtocol.
static u32 s_Handle = 0; // Handle for ReliableBroadcastProtocol.
void initializeTransport() { // Start the transport setup segment. nn::Result result = nn::pia::transport::BeginSetup(); PIA_ASSERT(result.IsSuccess()); // Code for creating a singleton of PiaTransport and the like. ... ... nn::pia::transport::Transport* pTransport = nn::pia::transport::Transport::GetInstance(); PIA_ASSERT(PIA_IS_VALID_POINTER(pTransport)); // Creation and initialization of ReliableBroadcastProtocol. Occurs during the interval between the BeginSetup() and EndSetup() functions. const u16 RELIABLE_BROADCAST_PROTOCOL_PORT = 0; // The port number used by ReliableBroadcastProtocol. s_Handle = pTransport->CreateProtocol<nn::pia::transport::ReliableBroadcastProtocol>(RELIABLE_BROADCAST_PROTOCOL_PORT); PIA_ASSERT(s_Handle != 0); // Make sure that the return value is not 0. The CreateProtocol() function returns 0 if the same protocol ID already exists. result = pTransport->GetProtocol<nn::pia::transport::ReliableBroadcastProtocol>(s_Handle)->Initialize(); PIA_ASSERT(result.IsSuccess()); // End the transport setup segment. result = nn::pia::transport::EndSetup(); PIA_ASSERT(result.IsSuccess()); } |
The application must create the data to be sent in advance and determine the data size. Data streaming is not supported.
The sender passes the send data, its size, and the behavior to occur at transfer to the StartSend() function and calls it. The transfer behavior is configured by an instance of the Configuration class. The configurable behaviors are as follows. For more information, see the API reference.
Calling the StartSend() function submits a receive request by the sender to the other station.
// Function to get a pointer for ReliableBroadcastProtocol.
nn::pia::transport::ReliableBroadcastProtocol* GetReliableBroadcastProtocol() { PIA_ASSERT(PIA_IS_VALID_POINTER(nn::pia::transport::Transport::GetInstance())); return nn::pia::transport::Transport::GetInstance()->GetProtocol<nn::pia::transport::ReliableBroadcastProtocol>(s_Handle); } const size_t SEND_DATA_SIZE = 8 * 1024 * 1024; // The size of the data to send. static u32 s_SendData[SEND_DATA_SIZE/sizeof(u32)]; // The instance of the send data. static nn::pia::transport::ReliableBroadcastProtocol::Configuration s_SendConfig; // Data transfer mode. void prepareSend() { // Preparations to send data. nn::pia::transport::ReliableBroadcastProtocol* pProtocol = GetReliableBroadcastProtocol(); nn::Result result = pProtocol->StartSend(s_SendData, sizeof(s_SendData), s_SendConfig); PIA_ASSERT(result.IsSuccess()); } |
When the sender calls the StartSend() function, a receive request is delivered to other stations participating in sessions (excluding the sender). The GetRequest() function can determine whether this receive request arrived. The GetRequest() function returns NULL if the request has not been delivered.
The calling of the StartReceive() function accepts the receive request that has arrived from the sender and starts the sending and receiving of data.
const size_t RECEIVE_BUFFER_SIZE = 8 * 1024 * 1024; // Receive buffer size.
static u32 s_ReceiveBuffer[RECEIVE_BUFFER_SIZE/sizeof(u32)]; // The instance of the receive buffer. void startReceive() { // After the receive request arrives, data receiving begins. nn::pia::transport::ReliableBroadcastProtocol* pProtocol = GetReliableBroadcastProtocol(); const nn::pia::transport::ReliableBroadcastProtocol::TransferSetting* cpRequest = pProtocol->GetRequest(); if (cpRequest != NULL) { nn::pia::StationId srcId = cpRequest->GetSourceStationId(); PIA_ASSERT(srcId != nn::pia::STATION_ID_INVALID); nn::Result result = pProtocol->StartReceive(s_ReceiveBuffer, sizeof(s_ReceiveBuffer), srcId); PIA_ASSERT(result.IsSuccess()); } } |
Use the GetState() function to determine whether the receiving of data has completed. The GetState()function returns STATE_RECEIVE_SUCCESS when all data has been received.
The return value of the GetState() function for the sender depends on the settings of the Configuration::IsSendEndless() function. For more information, see the API reference.
The following code is an example of the finalization for ReliableBroadcastProtocol.
void finalizeTransport()
{ nn::pia::transport::Transport* pTransport = nn::pia::transport::Transport::GetInstance(); PIA_ASSERT(PIA_IS_VALID_POINTER(pTransport)); // Finalization of ReliableBroadcastProtocol. nn::pia::transport::ReliableBroadcastProtocol* pProtocol = pTransport->GetProtocol<nn::pia::transport::ReliableBroadcastProtocol>(s_Handle); if (PIA_IS_VALID_POINTER(pProtocol)) { pProtocol->Finalize(); pTransport->DestroyProtocol(s_Handle); s_Handle = 0; } } |
The operations described earlier are the basic operations. This section describes the advanced operations.
Based on application specifications, when the sender and receiver are known in advance, it is possible for the receiving end to call the StartReceive() function before the sender calls the StartSend() function. Calling the StartReceive() function ahead of time slightly lessens the loss of data and can also slightly reduce the time needed for sending and receiving.
As noted, you can get the receive request with the GetRequest() function, but you can also reject the request. To do so, use the RejectRequest() function.
void rejectRequest()
{ nn::pia::transport::ReliableBroadcastProtocol* pProtocol = GetReliableBroadcastProtocol(); nn::Result result = pProtocol->RejectRequest(); PIA_ASSERT(result.IsSuccess()); } |
Call the Cancel() function to cancel a transfer midway.
void cancel()
{ nn::pia::transport::ReliableBroadcastProtocol* pProtocol = GetReliableBroadcastProtocol(); enum nn::pia::transport::ReliableBroadcastProtocol::State state = pProtocol->GetState(); if(state == nn::pia::transport::ReliableBroadcastProtocol::STATE_SENDING || state == nn::pia::transport::ReliableBroadcastProtocol::STATE_RECEIVING) { // Cancels sending and receiving. nn::Result result = pProtocol->Cancel(); PIA_ASSERT(result.IsSuccess()); } } |
You can check the progress of a transfer with the GetProgress() function, but note that the meaning of the returned value is different for the sender and the receiver.
When the receiver calls GetProgress(), all that is returned is the size of the data received. When the sender calls it, however, the average data size sent to all target stations is returned.
void printProgress()
{ nn::pia::transport::ReliableBroadcastProtocol* pProtocol = GetReliableBroadcastProtocol(); const nn::pia::transport::ReliableBroadcastProtocol::TransferSetting* cpSetting = pProtocol->GetCurrentTransferSetting(); if (cpSetting != NULL) { // Print the progress for the recipient. u32 total = cpSetting->m_DataSize; u32 current = pProtocol->GetProgress(); f32 rate = static_cast<f32>(current) / static_cast<f32>(total); PIA_BASIC_REPORT("%7dB / %7dB (%5.1f%%)", current, total, rate * 100.0f); } } |
Call the Reset() function to destroy the transfer result information and return to a State::STATE_WAIT state. The Reset() function cannot be called, however, during a transfer. For more information, see the API reference.
void reset()
{ nn::pia::transport::ReliableBroadcastProtocol* pProtocol = GetReliableBroadcastProtocol(); PIA_ASSERT(pProtocol->IsRunning() == false); nn::Result result = pProtocol->Reset(); PIA_ASSERT(result.IsSuccess()); } |