Start of trail Stream Server navigation bar

Table of Contents

Stream Client

Connects to a remote host and sends and/or receives data from that host.

Library

QUARC Targets/Communications/Basic

Description

Stream Client

The Stream Client block establishes a "persistent" connection with a host. The host may be local or remote. If the connection to the host is lost this block automatically attempts to reconnect to the host. The current state of the connection is available at the state output.

When the block is configured to receive data and data arrives, the new output is set to true and the data appears at the rcv output. The amount of data received is determined by the dimensions of the Default output value parameter and the data type specified in the Output data type field. Multi-dimensional signals and bus signals are supported.

When the block is configured to send data, the signal at the snd input is sent to the host each sampling instant in which the en input is non-zero. This signal may be multi-dimensional or a bus signal. The sent output is set to true (non-zero) if the data was sent. If the send operation would have blocked then the sent output is set to false (zero). If an error occurs then a standard negative QUARC error code is output at the err output. An error condition will cause the block to close the connection and attempt to reopen a new connection.

The basic Stream blocks are always non-blocking. They do not wait for data to be sent or to be received. However, the signals sent or received are always treated as atomic units - the block will never receive part of the data or send part of the data.

The Stream Client block supports a number of different communication options. It may be configured to use non-blocking I/O for the underlying stream or to use blocking I/O in separate threads. In either case, the block itself never waits for data to be sent or received and thus does not interfere with the sampling rate of the model. The blocking I/O option requires more knowledge to use but has the advantage that it reconnects faster when the connection is lost and typically requires less computation time in the control thread.

It may also be configured to maximize throughput or minimize latency. When maximizing throughput, the block buffers the data prior to flushing it to the underlying stream in order to make optimum use of the communications bandwidth available. However, this option can lead to latencies at the peer because the data is not necessarily sent immediately. The size of the buffers used for internally buffering the data are set via the Send buffer size and Receive buffer size parameters.

When the block is configured to minimize latency it flushes the data to the underlying stream every sampling instant. This option can result in poor use of the communications bandwidth but minimizes the time for the data to arrive at the host. For example, a single TCP/IP packet can store 1460 bytes of data, or 182 doubles. Supposed the Stream Client block is sending and receiving a single double. If send and receive buffer sizes are set to 1460 bytes, and the maximize throughput option is selected, then the Stream Client block will send 182 doubles in each TCP/IP packet, making efficient use of the communications bandwidth. However, if the minimize latency option is selected, then the Stream Client block will send one double in each TCP/IP packet. In this case there is a lot of wasted bandwidth but the latency is minimized.

In some circumstances, the server and client only need to exchange the most recent data and old data may be discarded. The Stream Client block supports this option as well, which also helps to minimize latency when only the most recent data is required.

Remote hosts are identified by a Universal Resource Identifier (URI), such as tcpip://remotehost:8000 or serial://remotehost:1?baud=57600. QUARC uses URI's for all its communications because it provides a uniform, extensible and flexible means of identifying the communication protocol to use and the associated communication parameters. Refer to Universal Resource Identifiers for more information.

The URI may be specified in the dialog parameters or via an input port. Which option is used is determined by the Source of URI parameter. When the URI is specified via an input, the input is typically driven by a Model Argument block, which allows a model argument to be used to assign the URI at runtime.

Warning

If the URI is specified via an input port, the Stream Client block only samples the input when the model is first started. Hence, the URI cannot be changed while the model is running.

The number of input ports depends on the Send options and Source of URI parameters. If the Send options field is set to Do not send data then the snd and en ports are not provided. If the Source of URI parameter is set to Specify via dialog (do not evaluate) or Specify via dialog (evaluate) then no uri input is provided. Refer to the documentation on these two parameters below for more details.

The number of output ports depends on the Send options and Receive options parameter. If the send options are set to Do not send data then the sent port is not provided. If the receive options are set to Do not receive data then the rcv and new ports are not provided. Refer to the documentation on the Send options and Receive options parameters below for more details.

Limitations

File protocol for writing

Warning To use the file protocol to write to a file, configure the Implementation for Use non-blocking I/O or set the Send options parameter to Send all data. Also configure the Receive options parameter as Do not receive data. Be sure to specify the mode=w option on the URI as well. For example, file:myfile.dat?mode=w.

File protocol for reading

Warning To use the file protocol to read from a file, configure the Implementation for Use non-blocking I/O or set the Receive options parameter to Receive all data. Also configure the Send options parameter as Do not send data. Be sure to specify the mode=r option on the URI as well. For example, file:myfile.dat?mode=r.

Because the Stream Client block maintains a persistent connection, it will read the file repeatedly because every time it reaches the end of file it closes the file and then "reconnects" i.e. re-opens it and reads it again. Use the Intermediate or Advanced Stream blocks to avoid this behaviour or look for a falling edge on the state output to detect when it finishes reading the file and ignore subsequent data.

Helpful Hints

Firewall

Hint If the server is remote then any firewall on the server must be configured to allow incoming access on the port being used.

Datagram size and UDP

Hint For packet or message-based protocols in non-blocking mode, the number of bytes sent over the communication channel in each packet may be larger than the number of bytes in the input signal, even if the block is configured to minimize latency. If the data cannot be flushed to the underlying communication channel without blocking then it remains in the stream buffer and will be written to the underlying communication channel along with the new data on the next sampling instant. This situation is typically recognized when a QERR_DATAGRAM_TOO_LARGE error is returned at the peer when trying to receive the data.

The number of bytes in each packet may be as large as the stream buffer size unless the underlying protocol restricts the maximum packet size. For example, the bufsize option of the UDP protocol has a default value of 1492 bytes. Hence, up to 1492/8 = 186 doubles may appear in a single datagram at the peer if the stream buffer is more than 1492 bytes in size. To restrict the size of the datagrams sent, either reduce the stream buffer size or set the bufsize option of the UDP URI. Reducing the stream buffer size may cause new data to be discarded if there is not enough room in the stream buffer, but it limits the number of datagrams sent. Setting the bufsize option of the UDP URI causes the stream API to send multiple datagrams, if necessary, to flush the stream buffer. A typical URI would be udp://localhost:18000?bufsize=512, which sets the maximum datagram size to 512 bytes (64 doubles).

An even better solution is to allow the datagrams to be large and instead receive the full datagram at the peer. For example, if the stream buffer size and maximum datagram size are both 1492 bytes, then attempt to receive 1492 bytes at the peer (or 187 doubles). For the Simulink blocks or stream API functions, that means using a stream buffer that is at least 1492 bytes in length at the peer. For the lower-level communications API, specify a buffer of at least 1492 bytes in the call to qcomm_receive.

Multiple NICs and UDP

Hint When using the UDP protocol, the network interface card (NIC) through which datagrams are sent may be specified using the nic option. This option is particularly useful when broadcasting datagrams in order to restrict broadcast messages to a particular NIC. Without the nic option, most operating systems send broadcast messages through all the NICs. However, Windows 7 and above do not broadcast to all NICs in this case, but chooses one arbitrarily. Hence, specifying the nic option allows the NIC used for broadcast messages to be controlled. Refer to the UDP Protocol for details.

Variable-size signals

Hint When using the Stream Client block with variable-size signals in subsystems, make sure any Action Port, Enable or Trigger ports are configured to propagate the sizes of variable-size signals during execution. Refer to Variable-Size Signals for more information on variable-size signals.

Input Ports

snd

The data to be sent to the peer. The data is sent each sampling instant in which the en input is non-zero, according to the other options. Multi-dimensional and variable-size signals are supported, as well as bus inputs. See Using Bus Objects with QUARC for more information on bus signals, and refer to Variable-Size Signals for more details on variable-size signals.

en

When this input is non-zero, the data at the snd port is transmitted. When this input is zero, the data at the snd port is ignored and not transmitted.

uri

A string specifying the URI to which to connect. The string must be a null-terminated vector of characters represented as a vector of uint8 quantities. It may be variable-sized. This string is typically provided either directly or indirectly by a Model Argument block or String Constant block.

This input is only available if the Source of URI parameter is set to External input port. Refer to the documentation below on the Source of URI parameter for details.

Output Ports

state

The current status of the connection. The possible states are tabulated below:

State

Name

Description

0

PSTREAM_STATE_NOT_CONNECTED

The stream is not connected.

1

PSTREAM_STATE_CONNECTING

The stream is attempting to connect (only occurs using non-blocking I/O).

2

PSTREAM_STATE_CONNECTED

The stream is connected to the host.

3

PSTREAM_STATE_CLOSING

The stream is closing the connection to the host.

err

If an error occurs sending and receiving the data, then this output is a negative QUARC error code indicating the cause of the problem. Otherwise it is zero.

If data could not be sent or received without blocking then this output is zero because this situation is not regarded as a fatal error condition. The sent and new outputs may be checked to determine whether data is actually sent or received in this case.

sent

An optional Boolean value indicating whether the input signal was written to the stream buffer successfully. This value will be true (non-zero) if the data was written successfully and zero otherwise. This output merely indicates that the data was written to the stream buffer. It does not validate that the data was sent to the underlying communication channel or delivered to the remote peer successfully.

If the data could not be written immediately without blocking then this output will be zero. Either increase the size of the stream buffer, slow down the sample time of the block or resend that data. If the communications bandwidth of the underlying communications hardware is insufficient to support the data rates required then increasing the stream buffer will only increase the time it takes before the stream buffer comes full because it cannot be flushed fast enough to the underlying stream. However, increasing the size of the stream buffer helps in situations where latencies in the communications are time-varying.

rcv

This optional output contains the data received from the peer. If data has yet to be received from the peer then it is set to the value specified in the Default output value parameter. If data has been received previously from the peer but there is no new data, then this output is set to the last value received. If new data has been received, then this output contains the new data. In this case, the new output will be true. The dimensions of the output are determined by the Default output value parameter, while its data type is specified in the Output data type field. Multi-dimensional and variable-size signals, as well as bus outputs are supported. See Using Bus Objects with QUARC for more information on bus signals, and refer to Variable-Size Signals for more details on variable-size signals.

new

This optional Boolean output indicates whether the rcv output is providing newly received data or old data. When new data has been received, this output is true (non-zero). Otherwise it is false (0), indicating that data could not be received without blocking.

Data Type Support

The Stream Client block outputs signals of any of the standard Simulink datatypes. The snd and rcv ports may be multi-dimensional or variable-size. Fixed-point datatypes are not currently supported. See Variable-Size Signals for more information on variable-size signals.

The Stream Client block also supports bus signals at its snd and rcv ports. Buses are useful for sending or receiving a mix of different data types in a single operation. Use the Simulink Bus Editor to create a Simulink.Bus object defining the bus. Then pass the name of this object in the Output type name parameter to receive a bus signal. It is convenient to save the bus object to a MAT file and then ensure that the bus object is always defined by loading this MAT file within the InitFcn callback of the Simulink model. See Using Bus Objects with QUARC for more information on bus signals.

Parameters and Dialog Box

Main Pane

The Main pane of the dialog appears as follows:

Main tab of Stream Client parameters dialog

Source of URI

Indicates whether the URI should be determined from the dialog parameters or an input port. If this field is set to Specify via dialog (do not evaluate) then the URI is specified via the URI of host to which to connect parameter. In this case, the URI is not evaluated as a MATLAB expression but is interpreted as a literal string. However, format specifiers are recognized. Refer to qc_perform_substitutions for a list of the format specifiers available.

Warning If format specifiers which change frequently, such as '%{time}' or '%{instance}', are used in the URI then the Stream Client block cannot be placed in a referenced model, because the URI will change from the time the code is built to when the code is run. As a result, Simulink will insist that the code be rebuilt because block parameters in referenced models are inlined. Instead, specify the source of the URI as External input port and pass the URI from the top-level model. Use a String Constant block in the top-level model to generate the URI.

If this field is set to Specify via dialog (evaluate) then the URI is also specified via the URI of host to which to connect parameter. However, in this case, the URI is evaluated as a MATLAB expression. This option is convenient for using a variable in the MATLAB workspace for the URI.

If this field is set to External input port then the URI of host to which to connect parameter is ignored and an extra input port is provided which determines the URI.

URI of host to which to connect (tunable offline)

The URI identifying the remote host to which to connect. This parameter identifies the communication protocol and associated parameters. For example, tcpip://quanser-dev:18000 connects to the remote host called quanser-dev using TCP/IP on port 18000. This field is only used if the Source of URI parameter is set to Specify via dialog (do not evaluate) or Specify via dialog (evaluate). Refer to Universal Resource Identifiers for more information about URIs and the communications protocols supported by QUARC.

Send buffer size in bytes (tunable offline)

The size of the buffer used for the stream for sending data. This buffer is independent of any buffering in the underlying communication protocol. Increasing the buffer size may increase performance when maximizing throughput. The buffer size must be at least as large as the maximum vector that will be sent. For example, if a double 3-vector is attached to the snd input, then the send buffer size must be at least 24 bytes in length since a double is 8 bytes and a 3-vector is being sent.

Receive buffer size in bytes (tunable offline)

The size of the buffer used for the stream for receiving data. This buffer is independent of any buffering in the underlying communication protocol. Increasing the buffer size may increase performance when maximizing throughput. The buffer size must be at least as large as the maximum vector that will be received. The size of the vector received is based on the length of the Default output value parameter and the data type selected on the Signal Data Types pane. For example, if a 5-vector of doubles is specified then the rcv output will be a 5-vector of doubles and the receive buffer size must be at least 40 bytes in length since a double is 8 bytes and a 5-vector is being received.

Byte ordering (tunable offline)

The order in which bytes are transmitted. Little endian ordering means that the least significant byte of individual values, such as doubles, is transmitted first. Big endian ordering means that the most significant byte of individual values is transmitted first.

Optimize for (tunable offline)

This option controls when data to be transmitted is flushed to the underlying stream. When this option is set to Maximum throughput then data to be sent is buffered until the stream send buffer is full. At that point, the entire buffer is flushed to the underlying communication channel. This approach may be used to maximize use of the communication bandwidth by ensuring that packets, for example, are full before being sent. However, it means that the data may not arrive at the peer in a timely fashion because the first data stored in the packet is "old" by the time the entire packet is sent.

To minimize such latencies, this option may be set to Minimum latency. In this case, the data is flushed to the underlying stream every sampling instant. Hence, the packets sent may not be full, but data arrives at the peer as soon as possible.

Send options

This parameter determines whether all the data that appears at the snd input is transmitted, or only the most recent data or none at all.

Receive options

This parameter determines whether all the data that is received appears at the rcv output, or only the most recent data or whether any data is received at all.

Default output value (tunable offline)

The value to output from the rcv output before any data has been received. This parameter also determines the size of the rcv output. The data type is set on the Signal Data Types pane. This parameter may be a multi-dimensional array, such as the 2x3 matrix: [0 0 0; 0 0 0].

For bus signals, this parameter must evaluate to a MATLAB structure containing the same fields as the bus signal itself. The data types and dimensions of those fields must also correspond to the bus signal. The MATLAB structure may be defined using the struct function in MATLAB or by defining it directly in the MATLAB command window and then using that workspace variable for this parameter.

Hint

It is recommended that this variable be saved as part of a MAT file (like the bus object). This MAT file should then be loaded from the InitFcn callback of the model (and possibly the PreLoadFcn callback as well) to ensure that the variable is always defined when required.

See Using Bus Objects with QUARC for more information on bus signals.

Sample time

The sample time of the block. A sample time of 0 indicates that the block will be treated as a continuous time block. A positive sample time indicates that the block is a discrete time block with the given sample time.

A sample time of -1 indicates that the block inherits its sample time. Since this is a source block, only inherent the sample time when it is placed in a conditionally executed subsystem, like a Triggered or Enabled Subsystem, or in a referenced model.

The default sample time is set to qc_get_step_size, which is a QUARC function that returns the fundamental sampling time of the model. Hence, the default sample time is a discrete sample time with the same sampling time as the fixed step size of the model.

Active during normal simulation (tunable offline)

Indicates whether this block should communicate during normal simulation. Whether it is active or not does not affect other Stream blocks in the diagram.

Advanced Pane

The Advanced pane of the dialog appears as follows:

Advanced Parameters tab of Stream Client parameters dialog

Implementation (tunable offline)

This option controls how the underlying communications is implemented by the block. When this option is set to Use non-blocking I/O then the block uses a non-blocking stream for the communications and employs a state machine to keep track of whether a connection has been established or not. Non-blocking I/O may only be used with communications protocols that support it. If non-blocking I/O is not supported by the underlying communication protocol then the Use blocking I/O in a separate thread option must be selected.

When this option is set to Use blocking I/O in a separate thread then the block uses a multi-threaded implementation in which sending and receiving of data from the peer is performed in two separate threads. The data to be sent or received is transferred between the block and these threads each sampling instant via a pair of FIFO queues (one for sending and one for receiving of data). The size of these queues may be set using the Send FIFO size and Receive FIFO size parameters. The priority of the send and receive threads may be set using the Send thread priority and Receive thread priority parameters. These parameters not visible when the Implementation parameter is set to Use non-blocking I/O.

Send FIFO size in samples (tunable offline)

The size of the FIFO queue used to transfer the data to be sent from the snd input to the send thread each sampling instant. The size of the queue is specified in samples, in which one sample represents the entire input vector collected at a single sampling instant. The size of the FIFO should be large enough to allow data to be collected for transmission while the send thread is in the process of transmitting the previous data.

Receive FIFO size in samples (tunable offline)

The size of the FIFO queue used to transfer the data received by the receive thread to the rcv output of the block each sampling instant. The size of the queue is specified in samples, in which one sample represents the entire output vector for a single sampling instant. The size of the FIFO should be large enough to allow data received asynchronously by the receive thread to be stored until the next sampling instant.

Send thread priority (tunable offline)

The priority of the send thread when the multi-threaded implementation is used. In general, a value of 0 indicates the lowest priority and higher values indicate a higher priority. The number of priority levels available depends on the type of QUARC target for which code is being generated.

Receive thread priority (tunable offline)

The priority of the receive thread when the multi-threaded implementation is used. In general, a value of 0 indicates the lowest priority and higher values indicate a higher priority. The number of priority levels available depends on the type of QUARC target for which code is being generated.

Send dimensions

This option is used with variable-sized signals. Checking this option causes the current dimensions of the snd input signal to be sent prior to the data itself so that the peer knows the dimensions of the signal. The block automatically determines the appropriate integer size required for each dimension based on the maximum dimensions of the input signal. For example, if the maximum size of a dimension is less than 256 then a single 8-bit integer is used to transmit that dimension. If the maximum size is less than 65536 then a 16-bit integer is used. Dimensions larger than 32-bits are not supported. See Variable-Size Signals for more information on variable-size signals.

Receive dimensions

This option is used with variable-sized signals. Checking this option causes the current dimensions of the output signal to be read from the stream prior to the data itself. The rcv output signal is then sized according to the received dimensions. The block automatically determines the type of integer required for each dimension based on the maximum dimensions of the output signal specified in the Maximum dimensions parameter. For example, if the maximum size of a dimension is less than 256 then a single 8-bit integer is received for that dimension. If the maximum size is less than 65536 then a 16-bit integer is used. Dimensions larger than 32-bits are not supported. See Variable-Size Signals for more information on variable-size signals.

Maximum receive dimensions

This parameter is only used when the Receive dimensions option is checked. It determines the maximum dimensions of the rcv output. It is a vector of positive integers indicating the dimensions required. For example, a value of 10 would make the output a vector of at most 10 elements. A value of [4 9] would make the output a matrix whose maximum size is 4x9.

If the Maximum dimensions is set to -1 then the maximum dimensions are inherited from the Default output value parameter. A vector value for the Default output value parameter will be treated as a 1-D vector rather than a matrix. To force the output to be a treated as a matrix, specify the dimensions explicitly in the Maximum receive dimensions parameter rather than inheriting from the Default value parameter.

Signal Data Types Pane

The Signal Data Types pane of the dialog appears as follows:

Signal Parameters tab of Stream Client parameters dialog

Output data type

Determines the data type of the data received. If back propagation is selected then the data type will be determined by the block to which the output is connected. If the output is not connected or it is connected to a block which supports multiple datatypes, then the output data type will be double.

If this field is set to Specify via dialog then the Output type name parameter is used to define the data type of the output. Refer to the Output type name parameter for details.

Output type name

This parameter should be the name of a variable in the MATLAB workspace that defines the data type of the output. This variable may be a Simulink.AliasType, Simulink.NumericType, Simulink.StructType or Simulink.Bus object. Simulink.Bus objects may be created using the Simulink Bus Editor, available from the Tools menu of the Simulink diagram.

Targets

Target Name

Compatible*

Model Referencing

Comments

QUARC Win32 Target

Yes

Yes

QUARC Win64 Target

Yes

Yes

QUARC Linux Nvidia Target

Yes

Yes

QUARC Linux QBot Platform Target

Yes

Yes

QUARC Linux QCar 2 Target

Yes

Yes

QUARC Linux QDrone 2 Target

Yes

Yes

QUARC Linux Raspberry Pi 3 Target

Yes

Yes

QUARC Linux Raspberry Pi 4 Target

Yes

Yes

QUARC Linux RT ARMv7 Target

Yes

Yes

QUARC Linux x64 Target

Yes

Yes

QUARC Linux DuoVero Target

Yes

Yes

QUARC Linux DuoVero 2016 Target

Yes

Yes

QUARC Linux Verdex Target

Yes

Yes

QUARC QNX x86 Target

Yes

Yes

Last fully supported in QUARC 2018.

Rapid Simulation (RSIM) Target

Yes

Yes

S-Function Target

No

N/A

Old technology. Use model referencing instead.

Normal simulation

Yes

Yes

* Compatible means that the block can be compiled for the target.

See Also

 

navigation bar