UDP-SENDER(1)

πŸ‘‘ UDP-SENDER β€” bestie edition πŸ’…

okay so real talk: this is the manual page for udp-sender, part of the Udpcast family. It's giving "one file, a whole LAN, zero drama." Sit down, grab a snack πŸ“, and let's get into it.


✨ NAME ✨

udp-sender β€” broadcast a file on a LAN πŸ¦‹


🌸 SYNOPSIS 🌸

udp-sender [--file file] [--full-duplex] [--half-duplex] [--pipe pipe]
[--portbase portbase] [--blocksize size] [--interface net-interface]
[--mcast-data-address data-mcast-address] [--mcast-rdv-address mcast-
rdv-address] [--max-bitrate bitrate] [--pointopoint] [--async] [--log
file] [--min-slice-size min] [--max-slice-size max] [--slice-size]
[--ttl time-to-live] [--fec stripesxredundancy/stripesize]
[--print-seed] [--rexmit-hello-interval interval] [--autostart
autostart] [--broadcast] [--min-receivers receivers] [--min-wait sec]
[--max-wait sec] [--nokbd] [--retries-until-drop n] [--bw-period n]
[--rate-governor module.so:key1=value1,key2=value2] [--stat-period n]
[--print-uncompressed-position flag]

πŸ’– DESCRIPTION πŸ’–

So udp-sender is the main character that broadcasts a file β€” think a disk image, or literally whatever you want β€” out to a bunch of udp-receivers chilling on the local LAN. 🫢

The way it does this? It uses Ethernet multicast or broadcast, so every single receiver gets to vibe off the same physical datastream. No cap. That means sending to 10 destinations does not take more time than sending to just 2. It's iconic like that. ✨


πŸŽ€ OPTIONS πŸŽ€

🧚 Basic options 🧚

  • --file file β€” pulls the data you wanna transmit out of file. No file supplied? Then it just reads the data from stdin instead. Easy.
  • --pipe command β€” runs your data through command before transmitting it. Lowkey so useful for compressing/decompressing, or stripping out unused blocks. The command gets a direct handle on the input file or device, so it can seek inside it if it needs to. Udpcast itself also keeps a handle on the file, and it uses that for an informal little progress display. The command's stdout is a pipe to udpcast. πŸ¦‹
  • --autostart n β€” kicks off transmission after n retransmissions of the hello packet, without waiting around for a key stroke. Perfect for unattended operation, like when udp-sender is started from a cron-job for a broadcast/multicast at a scheduled time. ⏰

🌈 Networking options 🌈

heads up bestie: these next ones should be supplied both on the sender and the receivers. both sides, okay? πŸ’…
  • --portbase portbase β€” the default ports to use for udpcast. Two ports get used: portbase and portbase+1. So portbase must be even. Default is 9000. Same portbase has to be specified for both udp-sender and udp-receiver, no exceptions.
  • --interface interface β€” the network interface used to send out the data. Default is "eth0".
  • --ttl time to live β€” sets the time-to-live parameter for the multicast packets. Theoretically this should let you use UDPCast beyond the local network, but it's not been tested, for lack of a multicast router. πŸ™ˆ
  • --mcast-rdv-address address β€” uses a non-standard multicast address for the control (rendez-vous) connection. This is the address the sender and receivers use to "find" each other. It is not the address used to transfer the actual data. By default mcast-rdv-address is the Ethernet broadcast address if "ttl" is 1, and 224.0.0.1 otherwise. You should not use this setting except in very special situations, like when 224.0.0.1 can't be used for policy reasons.

πŸ‘‘ Networking options β€” sender-only edition πŸ‘‘

these ones get supplied only on the sender, bestie. don't go putting them on the receivers.
  • --mcast-data-address address β€” uses the given address for multicasting the data. If you don't specify one, the program automatically derives a multicast address from its own IP β€” by keeping the last 27 bits of the IP and then prepending 232.
  • --pointopoint β€” point-to-point mode. Only a single receiver is allowed, but the data gets sent directly to that receiver (unicast mode) instead of multicast/broadcast all over the place. If no async mode is chosen and there happens to be only one receiver, point-to-point activates automatically. 🎯
  • --nopointopoint β€” don't use point-to-point, even if there's only one single receiver. That's it. That's the whole option.
  • --full-duplex β€” use this if you're on a full-duplex network. T-base-10 or 100 is full duplex when it's equipped with a switch. Hub based networks, or T-base-2 networks (coaxial cable), are only half-duplex, and you should not use this option with those, or else you may experience a 10% performance hit. 😭 N.B. On high-latency WAN links, the full-duplex option can lead to substantial performance improvements, because it lets udp-sender send more data while it's still waiting for the previous batch to get acknowledged.
  • --half-duplex β€” use half duplex mode (needed for Hub based or T-base-2 networks). This is the default behavior in this version of udpcast.
  • --broadcast β€” use Ethernet broadcast rather than multicast. Useful if you've got Ethernet cards that don't support multicast. By default, "udpcast" uses multicast. This lets it send data only to those receivers that requested it. Ethernet cards of machines that aren't participating in the transmission automatically block out the packets at the hardware level. And on top of that, network switches can selectively transmit packets only to those network ports where receivers are connected. Both features together = much more efficient operation than broadcast. This option should only be supplied on the sender.
  • -b blocksize β€” chooses the packet size. Default (and also maximum) is 1456.

πŸ¦‹ Unidirectional mode (no return channel, we're on our own) πŸ¦‹

The options below are your besties in situations where there's no "return channel" available, or where such a channel is just impractical because of high latency. In a unidirectional setup (i.e. without a return channel), the sender only sends data and doesn't expect any reply from the receiver. πŸ“‘

⚠️ Unidirectional options must be used together, or else the transfer will not work correctly. Like, for real.

You may for example use the following command line:

udp-sender --async --max-bitrate 10m --fec 8x8
  • --async β€” asynchronous mode. Do not request confirmations from the receiver. Best used together with forward error correction and bandwidth limitation, or else the receiver will abort the reception as soon as it misses a packet. When the receiver aborts the reception like that, it prints a list of packets lost in the slice that caused the problem. You can use that list to tune the forward error correction parameters. πŸ”₯
  • --max-bitrate bitrate β€” limits the bandwidth used by udpcast. Useful in asynchronous mode, or else the sender may send too fast for the switch and/or receiver to keep up. Bitrate can be expressed in bits per second (--bitrate 5000000), kilobits per second ("--bitrate 5000k") or megabits per second ("--bitrate 5m"). This is the raw bitrate, including packet headers, forward error correction, retransmissions, etc. Actual payload bitrate will be lower.
  • --fec interleave"x"redundancy"/"stripesize β€” enables forward error correction. The goal of FEC is to transmit redundant data, in order to make up for packets lost in transit. Because, yeah, in unidirectional mode the receivers have no way of requesting retransmission of lost packets, so the only way to address packet loss is to include redundant information to begin with. The algorithm is designed such that if r redundant packets are transmitted, those can be used to compensate for the loss of any r packets in the same FEC group (stripe). In order to increase robustness of the FEC algorithm against burst packet losses, each slice is divided into interleave stripes. Each stripe has stripesize blocks (if not specified, stripesize is calculated by diving slice-size by interleave). For each stripe, redundancy FEC packets are added. Stripes are organized in such a fashion that consecutive packets belong to different stripes. This way, we ensure that burst losses affect different stripes, rather than using all FEC packets of a single stripe. Example: "--fec 8x8/128"
  • --rate-governor module.so:key1=value1,key2=value2 β€” applies a dynamically loadable rate governor. module.so is the name of the preloadable module, which is followed by a number of property assignments (key1=value1). The rate governor controls the transmission rate according to various criteria, such as congestion information received from a routing or encapsulating device. See comments in "/usr/include/udpcast/rateGovernor.h" and example in "examples/rateGovernor" for more details.
  • --rexmit-hello-interval timeout β€” if set, rebroadcasts the HELLO packet used for initiating the casting, each timeout milliseconds. This option is useful together with asyc mode, because with async mode the receiver won't send a connection request to the sender (and hence won't get a connection reply). In async mode, the receivers get all needed information from the hello packet instead, so they're particularly dependent on receiving that packet β€” which makes retransmission useful. πŸ’« This option is also useful on networks where packet loss is so high that even with connection requests, sender and receiver would not find each other otherwise.
  • --retries-until-drop retries β€” how many times to send a REQACK until dropping a receiver. Lower retrycounts make "udp-sender" faster to react to crashed receivers, but they also increase the probability of false alerts β€” i.e. dropping receivers that aren't actually crashed, but merely slow to respond for whatever reason. πŸ’€
  • --streaming β€” allows receivers to join an ongoing transmission mid through. 🌊

πŸ™ˆ Keyboardless mode πŸ™ˆ

The options below help you run a sender in unattended mode. No hands, no keyboard, no problem.

  • --min-receivers n β€” automatically start as soon as a minimal number of receivers have connected. 🫢
  • --min-wait t β€” even when the necessary amount of receivers have connected, still wait until t seconds since first receiver connection have passed.
  • --max-wait t β€” when not enough receivers have connected (but at least one), start anyways when t seconds since first receiver connection have passed.
  • --nokbd β€” do not read start signal from keyboard, and do not display any message telling the user to press any key to start. (Because there is no user. There is only cron. πŸ‘‘)
  • --start-timeout sec β€” sender aborts at start if it doesn't see a receiver within this many seconds. Furthermore, transmission of data needs to start within this delay. Once transmission is started, the timeout no longer applies.

...and that's part 1, bestie β€” more is coming, don't you dare close the tab πŸ’œ

  • --daemon-mode β€” bestie, this one says don't leave when the job's done. Instead, hang around and wait for the next batch of receivers to pull up. And if you pass it twice? πŸ‘€ udp-sender fully commits β€” it puts itself into the background, closes its standard file descriptors, and becomes an actual real daemon. main character energy fr.
  • --pid-file file β€” lets you pick a pid file, iconic. If it comes together with --daemon-mode, udp-sender writes its pid into that file. And if it comes together with --kill, then the process with the given pid gets killed. πŸ’€
  • --kill β€” shuts down the udp-sender identified by the pid file (which, yes, you also have to specify β€” it's a package deal). Important: --kill does not interrupt an ongoing transmission, it just waits until it's finished. Patient queen behavior. πŸ‘‘

Example πŸ’…

udp-sender -f zozo --min-receivers 5 --min-wait 20 --max-wait 80
  • If one receiver connects at 18h00.00, and 4 more within the next 5 minutes, start at 18h00.20. (that's 5 receivers connected, but min-wait hasn't passed yet)
  • If one receiver connects at 18h00.00, and 3 more within the next 5 minutes, then a last one at 18h00.25 β€” start right after.
  • If one receiver connects at 18h00.00, then 3 more within the next 15 minutes, then nobody shows, start at 18h01.20. (not enough receivers, but we start anyways after max-wait)

πŸ“Š Logging and statistics options πŸ“Š

These options tell udp-sender to log some extra stats into a file:

  • --stat-period seconds β€” every so much milliseconds, it prints some statistics to stderr: how much bytes sent so far log, position in uncompressed file (if applicable), retransmit count... By default this gets printed every half second. Spammy but honest 🫢
  • --print-uncompressed-position flag β€” by default, udp-sender only prints the position in the uncompressed file if these 2 conditions are met:
    • Input is piped via a compressor (-p option).
    • The primary input is seekable (file or device).

With the --print-uncompressed-position options, you can change this behavior:

  • If flag is 0, uncompressed position will never be printed, even if above conditions are met.
  • If flag is 1, uncompressed position will always be printed, even if above conditions are not met.
  • --log file β€” logs some stuff into file. That's it, that's the whole vibe.
  • --no-progress β€” do not display progress statistics. no progress bar, no yapping 🌸
  • --bw-period seconds β€” every so much seconds, log the instantaneous bandwidth seen during that period. Note: this is different from the bandwidth displayed to stderr of the receiver, which is the average since start of transmission. two different girls, don't mix them up ✨

πŸŽ›οΈ Tuning options (sender) πŸŽ›οΈ

Okay so the following tuning options are all about slice size. Udpcast groups its data in slices, which are a series of blocks (UDP packets). These groups are relevant for:

  • data retransmission: after each slice, the server asks the receivers whether they have received all blocks, and if needed retransmits what has been missing
  • forward error correction: each slice has its set of data blocks, and matching FEC blocks.
  • --min-slice-size size β€” minimum slice size (expressed in blocks). Default is 16. When dynamically adjusting slice size (only in non-duplex mode), never use smaller slices than this. Ignored in duplex mode (default).
  • --max-slice-size size β€” maximum slice size (expressed in blocks). Default is 1024. When dynamically adjusting slice size (only in non-duplex mode), never use larger slices than this. Ignored in duplex mode (default).
  • --default-slice-size size β€” the slice size used (starting slice size in half-duplex mode).
  • --rehello-offset offs β€” in streaming mode, how many packets before end of slice the hello packet will be transferred (default 50). Chose larger values if you notice that receivers are excessively slow to pick up running transmission. πŸ¦‹

🧚 Tuning the forward error correction 🧚

There are three parameters on which to act:

  • redundancy β€” this influences how much extra packets are included per stripe. The higher this is, the more redundancy there is, which means that the transmission becomes more robust against loss. However, CPU time necessary is also proportional to redundancy (a factor to consider on slow PC's), and of course, a higher redundancy augments the amount of data to be transmitted.
  • interleave β€” this influences among how many stripes the data is divided. Higher interleave improves robustness against burst loss (for example, 64 packets in a row...). It doesn't increase robustness against randomly spread packet loss. Note: interleave bigger than 8 will force a smaller stripesize, due to the fact that slicesize is limited to 1024.
  • stripesize β€” how many data blocks there are in a stripe. Due to the algorithm used, this cannot be more than 128. Reducing stripe size is an indirect way of augmenting (relative) redundancy, without incurring the CPU penalty of larger (absolute) redundancy. However, a larger absolute redundancy is still preferable over a smaller stripesize, because it improves robustness against clustered losses. For instance, if 8/128 is preferable over 4/64, because with 8/128 the 8 FEC packets can be used to compensate for the loss of any of the 128 data packets, whereas with 4/64, each group of 4 FEC packets can only be used against its own set of 64 data packets. If for instance the first 8 packets were lost, they would be recoverable with 8/128, but not with 4/64.

Considering these, change parameters as follows:

  • If you observe long stretches of lost packets, increase interleave.
  • If you observe that transfer is slowed down by CPU saturation, decrease redundancy and stripesize proportionnally.
  • If you observe big variations in packet loss rate, increase redundancy and stripesize proportionnally.
  • If you just observe high loss, but not necessarily clustered in any special way, increase redundancy or decrease stripesize.
  • Be aware that network equipment or the receiver may be dropping packets because of a bandwidth which is too high. Try limiting it using max-bitrate.
  • The receiver may also be dropping packets because it cannot write the data to disk fast enough. Use hdparm to optimize disk access on the receiver. Try playing with the settings in /proc/sys/net/core/rmem_default and /proc/sys/net/core/rmem_max, i.e. setting them to a higher value.

πŸ‘€ SEE ALSO πŸ‘€

udp-receiver


πŸ’– AUTHOR πŸ’–

Alain Knaff


and that's a wrap bestie!! πŸŽ€ this page is the current version, dated February 17, 2024, from the UDP-SENDER(1) era β€” go forth and multicast, no cap. πŸ’…βœ¨

πŸ“¦ where this page comes from