Direct streaming provides features for simple sending and receiving.
You must first call the DirectStream::Enable
function before you can send or receive using direct streaming. Calling DirectStream::Enable
enables you to send and receive using direct streaming. Until this function is enabled, received packets are discarded within the library.
When you do not need direct streaming anymore, call the DirectStream::Disable
function to disable sending and receiving using direct streaming. However, even when disabled, any data already accumulated in the send queue is still sent. On the receiving end, responses to arrival confirmations for Reliable
communication, described later, are handled within the library.
Direct streaming supports two types of communication. The following sections describe the characteristics of each type.
You can select whether to use the PRUDP protocol implemented on UDP, with or without reliability.
Data sent is not guaranteed to arrive.
Use this for more efficient communication when you do not need to guarantee delivery.
With standard settings, both duplicate packets and packets that are out of order arrive
Perform the following configuration to guarantee that packets are in the right order and to resolve problems where packets are received out of order or the same packet is received several times. With this configuration, packets for which the order is unusual are destroyed starting from the oldest packet.
RootTransport::EnableDropDuplicateReorderingUnreliablePackets(true);
Data sent is guaranteed to arrive.
It is guaranteed that the order the packets are sent is the order in which they arrive. Also, lost packets are resent and duplicate packets are destroyed.
Because a transmission error can occur when the network is clogged because of packet transmission performance or a lost occurrence state, you must use a retry process in addition to error handling when performing frequent transmissions.
Call the DirectStream::Send
function to send packets to a specific station participating in the session. This function returns successfully after the data to send is added to the send queue, and returns an error if the function could not add the data to the queue. Send data added to the send queue is sent when either the Scheduler::Dispatch
function or the Scheduler::DispatchAll
function is called.
You can specify all of the communication types in calls to the DirectStream::Send
function.
The DirectStream::SendUnreliable
is a function for unreliable sends without specifying call context.
There is an overloaded version of the DirectStream::Send
function that allows you to specify a call context. This function returns true
after the data to send is added to the send queue, and returns false
if the function could not add the data to the queue.
Using a call context allows you to use an asynchronous process to receive arrival confirmations for packets sent using reliable communication. Use a context when you want to explicitly use arrival confirmations in your game application. After arrival is confirmed, the call context changes to the CallSuccess
state. After calling the DirectStream::Disable
function, the asynchronous process that receives arrival confirmations stops. In that case, you must cancel the call context from the game application side.
Other communication types besides reliable do not need arrival confirmation, so the results of adding data to the send queue are returned to the call context.
Call the DirectStream::SendUnreliableAll
function to send unreliable packets to all stations participating in the session. This function returns successfully after the data to send to all stations is added to the send queue, and returns an error if the function could not add the data to the queue.
You cannot specify a call context when sending to all stations.
With the standard settings, because the reliable queue is a single queue, if the network environment is bad, subsequent data never arrives because of head-of-line blocking.
By using multiple separate reliables (each reliable is called a substream), independent resend control can be performed. Instead of guaranteeing arrival order between substreams, clogging can be avoided for transmissions by resending important data. By specifying the user substream count used by the StreamSettings::SetMaxUserReliableSubStreams
function when initializing NetZ, a maximum of 256 reliable communications to match the system shared substreams at initialization (ID is SubStreamIDDefine::SYSTEM
) are possible.
Reliable communications that specify SubStreamID
are performed with the DirectStream::SendReliable
function.
If the system and shared substreams are clogged because a delay occurs in the fault recovery process, use at least one user substream, and exchange data by using that substream.
The following examples of SubStreamID
are able to use 0 to 2 substreams. SubStreamID 0 (= SubStreamIDDefine::SYSTEM)
is shared with the system, and is the same as when reliable communications are performed with the DirectStream::Send
function.
Code 7.1 Initialization Example When Using Multiple Substreams
NetZ *poNetZ = qNew NetZ;
Stream::GetSettings().SetMaxUserReliableSubStreams(2);
....
// The JoinSession or CreateSession process.
When the communication partner and the StreamSettings::SetMaxUserReliableSubStreams
function value differ, the smallest is determined to be the greatest substream ID by negotiation. QERROR(Transport, InvalidSubStreamID)
occurs when an ID exceeding the greatest substream ID is specified during sends.
To view sample code, see the AutoMatch
sample.
Warning
To send data immediately after communication completes, use the SubStreamIDDefine::SYSTEM (=0)
that is shared with the system. On occasion, the data may not arrive by the time communication completes.
An excessive number of substreams consumes memory, so use a suitable number.
Also, NEX reliable communications perform resend control but do not perform collision congestion control. For this reason, when multiple substreams are in parallel and too much data clogs, resends occur frequently and the loss rate increases. When sending a large volume of data, use a single substream.
The maximum sending size for unreliable communication is limited by the MTU. Because a NEX header is included in the MTU, be sure to use a transmission size of 1300 bytes or less if the topology of the NetZ network is peer-to-peer, or 1250 bytes or less in other cases.
For reliable communication, you can specify a buffer size of up to 32768 bytes when sending, but the portion larger than the MTU is split into chunks for sending.
When the maximum number of send buffers has been reached for sending reliable communication data, the sending process returns the ReliableSendBufferFull
error.
The ReliableSendBufferFull error indicates that the send buffer was temporarily full, so when this error occurs, dispatch the data and then wait briefly before trying to send the data again. The reliable communication send buffer also includes reliable communication packets used internally by NEX, in addition to packets sent by direct stream.
You can get the number of packets in the send buffer during reliable communications by using the DirectStream::GetPendingReliableBufferNum
function. The value that is obtained by using the DirectStream::GetPendingReliableBufferNum
function includes reliable communication packets that are used internally in NEX, in addition to unreliable communication packets that are used for direct streaming.
Call the DirectStream::SetMaxReliableSendBufferNum
function to change the maximum number of reliable communication send buffers. The standard default value is usually enough, because not many reliable communication packets are used internally by NEX. Do not set a value greater than 96. Call the DirectStream::GetMaxReliableSendBufferNum
function to get the current value.
Except for certain P2P communications, the buffer for packets is managed by the packet buffer manager in a fixed-length memory pool. As long as there is enough space in the packet buffer, no error is thrown until the maximum number of send buffers is reached for reliable communication. QRESULT_ERROR(Transport, PacketBufferFull)
is returned when the packet buffer runs out of space. If PacketBufferFull
is thrown, dispatch the data and wait briefly before trying to send the data again. If PacketBufferFull
occurs frequently, increase the size of the packet buffer. For more information about the packet buffer, see Managing Packet Buffer Memory in Memory Management.
Sending fails and returns an error in the following cases.
NetZ
object has finished being created, or while the NetZ
object is in the process of being destroyed.DirectStream::SendAll
function.SubStreamID
with the DirectStream::SendReliable
function that exceeds the greatest substream ID.PacketBufferFull
error).The call context is specified when sending data. An error is returned to the call context if communication with the destination station is lost.
When using reliable communication to send data, the ReliableSendBufferFull
error is returned if the send buffer is full. The ReliableSendBufferFull
error indicates that the send buffer was temporarily full, so when this error occurs, dispatch the data and then wait briefly before trying to send the data again.
PacketBufferFull
is thrown when the packet buffer runs out of space. The PacketBufferFull
error indicates that the packet buffer was temporarily full. When this error occurs, dispatch the data and wait briefly before trying to send the data again if necessary. If PacketBufferFull
occurs frequently, increase the size of the packet buffer. For more information about the packet buffer, see Managing Packet Buffer Memory in Memory Management.
Received packets are stored in the direct stream receive buffer when either the Scheduler::Dispatch
function or the Scheduler::DispatchAll
function is called. You can get received data stored in the receive buffer by calling the DirectStream::GetReceivedData
function. With the DirectStream::Data
structure, you can get the sender's StationID
, transmission type, packet buffer, and SubStreamID
from the received data.
The direct stream receive buffer is not cleared until the DirectStream::GetReceivedData
function is called. You must be sure to periodically call the DirectStream::GetReceivedData
function along with the Scheduler::Dispatch
or Scheduler::DispatchAll
function so that calls to the Scheduler::Dispatch
and Scheduler::DispatchAll
functions do not cause too much receive data to accumulate in the direct stream receive buffer. The fatal error QRESULT(Transport, NoBuffer)
is generated when the receive buffer overflows.
For more information about handling fatal errors, see Chapter 4 Error Handling.
If the receive buffer overflows, reduce the number of packets sent from other Stations, or increase how often the DirectStream::GetReceivedData
function is called along with the Scheduler::Dispatch
function or Scheduler::DispatchAll
function.
CONFIDENTIAL