#hs.socket.udp

Talk to custom protocols using asynchronous UDP sockets.

For TCP sockets see hs.socket.

You can do a lot of neat trivial and non-trivial things with these. A simple ping ponger:

function ping(data, addr) print(data) addr = hs.socket.parseAddress(addr) hs.timer.doAfter(1, function() client:send("ping", addr.host, addr.port) end) end function pong(data, addr) print(data) addr = hs.socket.parseAddress(addr) hs.timer.doAfter(1, function() server:send("pong", addr.host, addr.port) end) end server = hs.socket.udp.server(9001, pong):receive() client = hs.socket.udp.new(ping):send("ping", "localhost", 9001):receive()

Resulting in the following endless exchange:

20:26:56 LuaSkin: (secondary thread): Data written to UDP socket LuaSkin: (secondary thread): Data read from UDP socket ping 20:26:57 LuaSkin: (secondary thread): Data written to UDP socket LuaSkin: (secondary thread): Data read from UDP socket pong 20:26:58 LuaSkin: (secondary thread): Data written to UDP socket LuaSkin: (secondary thread): Data read from UDP socket ping 20:26:59 LuaSkin: (secondary thread): Data written to UDP socket LuaSkin: (secondary thread): Data read from UDP socket pong ...

You can do some silly things with a callback factory and enabling broadcasting:

local function callbackMaker(name) local fun = function(data, addr) addr = hs.socket.parseAddress(addr) print(name.." received data:\n"..data.."\nfrom host: "..addr.host.." port: "..addr.port) end return fun end local listeners = {} local port = 9001 for i=1,3 do table.insert(listeners, hs.socket.udp.new(callbackMaker("listener "..i)):reusePort():listen(port):receive()) end broadcaster = hs.socket.udp.new():broadcast() broadcaster:send("hello!", "255.255.255.255", port)

Since neither IPv4 nor IPv6 have been disabled, the broadcast is received on both protocols ('dual-stack' IPv6 addresses shown):

listener 2 received data: hello! from host: ::ffff:192.168.0.3 port: 53057 listener 1 received data: hello! from host: ::ffff:192.168.0.3 port: 53057 listener 3 received data: hello! from host: ::ffff:192.168.0.3 port: 53057 listener 1 received data: hello! from host: 192.168.0.3 port: 53057 listener 3 received data: hello! from host: 192.168.0.3 port: 53057 listener 2 received data: hello! from host: 192.168.0.3 port: 53057

#API Overview

Variables - Configurable values

Functions - API calls offered directly by the extension

Constructors - API calls which return an object, typically one that offers API methods

Methods - API calls which can only be made on an object returned by a constructor


#API Documentation

#Variables

Signaturehs.socket.udp.timeout
TypeVariable
DescriptionTimeout for the socket operations, in seconds.
Notes
  • New hs.socket.udp objects will be created with this timeout value, but can individually change it with the hs.socket.udp:setTimeout method.
  • If the timeout value is negative, the operations will not use a timeout. The default value is -1.
Sourceextensions/socket/socket.lua line 173

#Functions

Signaturehs.socket.udp.parseAddress(sockaddr) -> table or nil
TypeFunction
DescriptionAlias for hs.socket.parseAddress
Parameters
    Returns
      NotesNone
      Sourceextensions/socket/socket.lua line 184

      #Constructors

      Signaturehs.socket.udp.new([fn]) -> hs.socket.udp object
      TypeConstructor
      DescriptionCreates an unconnected asynchronous UDP socket object.
      Parameters
      • fn - An optional callback function for reading data from the socket, settable here for convenience.
      Returns
      NotesNone
      ExamplesNone
      Sourceextensions/socket/libsocket_udp.m line 111

      Signaturehs.socket.udp.server(port[, fn]) -> hs.socket.udp object
      TypeConstructor
      DescriptionCreates a UDP socket, and binds it to a port for listening.
      Parameters
      • port - A port number [0-65535]. Ports [1-1023] are privileged. Port 0 allows the OS to select any available port.
      • fn - An optional callback function for reading data from the socket, settable here for convenience.
      Returns
      NotesNone
      ExamplesNone
      Sourceextensions/socket/socket.lua line 208

      #Methods

      Signaturehs.socket.udp:broadcast([flag]) -> self or nil
      TypeMethod
      DescriptionEnables broadcasting on the underlying socket.
      Parameters
      • flag - An optional boolean: true to enable broadcasting, false to disable it. Defaults to true.
      Returns
      Notes
      • By default, the underlying socket in the OS will not allow you to send broadcast messages.
      • In order to send broadcast messages, you need to enable this functionality in the socket.
      • A broadcast is a UDP message to addresses like "192.168.255.255" or "255.255.255.255" that is delivered to every host on the network.
      • The reason this is generally disabled by default (by the OS) is to prevent accidental broadcast messages from flooding the network.
      ExamplesNone
      Sourceextensions/socket/libsocket_udp.m line 418

      Signaturehs.socket.udp:close() -> self
      TypeMethod
      DescriptionImmediately closes the socket, freeing it for reuse. Any pending send operations are discarded.
      Parameters
      • None
      Returns
      NotesNone
      ExamplesNone
      Sourceextensions/socket/libsocket_udp.m line 222

      Signaturehs.socket.udp:closed() -> bool
      TypeMethod
      DescriptionReturns the closed status of the socket.
      Parameters
      • None
      Returns
      • true if the socket is closed, otherwise false.
      Notes
      • UDP sockets are typically meant to be connectionless.
      • Sending a packet anywhere, regardless of whether or not the destination receives it, opens the socket until it is explicitly closed.
      • An active listening socket will not be closed, but will not be 'connected' unless the hs.socket.udp:connect method has been called.
      ExamplesNone
      Sourceextensions/socket/libsocket_udp.m line 675

      Signaturehs.socket.udp:connect(host, port[, fn]) -> self or nil
      TypeMethod
      DescriptionConnects an unconnected socket.
      Parameters
      • host - A string containing the hostname or IP address.
      • port - A port number [1-65535].
      • fn - An optional single-use callback function to execute after establishing the connection. The callback receives no parameters.
      Returns
      Notes
      • * By design, UDP is a connectionless protocol, and connecting is not needed.
      • * Choosing to connect to a specific host/port has the following effect:
      • You will only be able to send data to the connected host/port;
      • You will only be able to receive data from the connected host/port;
      • You will receive ICMP messages that come from the connected host/port, such as "connection refused".
      • * The actual process of connecting a UDP socket does not result in any communication on the socket, it simply changes the internal state of the socket.
      • * You cannot bind a socket for listening after it has been connected.
      • * You can only connect a socket once.
      ExamplesNone
      Sourceextensions/socket/libsocket_udp.m line 145

      Signaturehs.socket.udp:connected() -> bool
      TypeMethod
      DescriptionReturns the connection status of the socket.
      Parameters
      • None
      Returns
      • true if connected, otherwise false.
      Notes
      • UDP sockets are typically meant to be connectionless.
      • This method will only return true if the hs.socket.udp:connect method has been explicitly called.
      ExamplesNone
      Sourceextensions/socket/libsocket_udp.m line 652

      Signaturehs.socket.udp:enableIPv(version[, flag]) -> self or nil
      TypeMethod
      DescriptionEnables or disables IPv4 or IPv6 on the underlying socket. By default, both are enabled.
      Parameters
      • version - A number containing the IP version (4 or 6) to enable or disable.
      • flag - A boolean: true to enable the chosen IP version, false to disable it. Defaults to true.
      Returns
      Notes
      • Must be called before binding the socket. If you want to create an IPv6-only server, do something like:
      • hs.socket.udp.new(callback):enableIPv(4, false):listen(port):receive()
      • The convenience constructor hs.socket.server will automatically bind the socket and requires closing and relistening to use this method.
      ExamplesNone
      Sourceextensions/socket/libsocket_udp.m line 486

      Signaturehs.socket.udp:info() -> table
      TypeMethod
      DescriptionReturns information about the socket.
      Parameters
      • None
      Returns
      • A table containing the following keys:
      • connectedAddress - string (sockaddr struct)
      • connectedHost - string
      • connectedPort - number
      • isClosed - boolean
      • isConnected - boolean
      • isIPv4 - boolean
      • isIPv4Enabled - boolean
      • isIPv4Preferred - boolean
      • isIPv6 - boolean
      • isIPv6Enabled - boolean
      • isIPv6Preferred - boolean
      • isIPVersionNeutral - boolean
      • localAddress - string (sockaddr struct)
      • localAddress_IPv4 - string (sockaddr struct)
      • localAddress_IPv6 - string (sockaddr struct)
      • localHost - string
      • localHost_IPv4 - string
      • localHost_IPv6 - string
      • localPort - number
      • localPort_IPv4 - number
      • localPort_IPv6 - number
      • maxReceiveIPv4BufferSize - number
      • maxReceiveIPv6BufferSize - number
      • timeout - number
      • userData - string
      NotesNone
      ExamplesNone
      Sourceextensions/socket/libsocket_udp.m line 699

      Signaturehs.socket.udp:listen(port) -> self or nil
      TypeMethod
      DescriptionBinds an unconnected socket to a port for listening.
      Parameters
      • port - A port number [0-65535]. Ports [1-1023] are privileged. Port 0 allows the OS to select any available port.
      Returns
      NotesNone
      ExamplesNone
      Sourceextensions/socket/libsocket_udp.m line 192

      Signaturehs.socket.udp:pause() -> self
      TypeMethod
      DescriptionSuspends reading of packets from the socket.
      Parameters
      • None
      Returns
      Notes
      • Call one of the receive methods to resume.
      ExamplesNone
      Sourceextensions/socket/libsocket_udp.m line 243

      Signaturehs.socket.udp:preferIPv([version]) -> self
      TypeMethod
      DescriptionSets the preferred IP version: IPv4, IPv6, or neutral (first to resolve).
      Parameters
      • version - An optional number containing the IP version to prefer. Anything but 4 or 6 else sets the default neutral behavior.
      Returns
      Notes
      • If a DNS lookup returns only IPv4 results, the socket will automatically use IPv4.
      • If a DNS lookup returns only IPv6 results, the socket will automatically use IPv6.
      • If a DNS lookup returns both IPv4 and IPv6 results, then the protocol used depends on the configured preference.
      ExamplesNone
      Sourceextensions/socket/libsocket_udp.m line 523

      Signaturehs.socket.udp:read(delimiter[, tag]) -> self
      TypeMethod
      DescriptionAlias for hs.socket.udp:receive
      Parameters
        Returns
          NotesNone
          Sourceextensions/socket/socket.lua line 237

          Signaturehs.socket.udp:readOne(delimiter[, tag]) -> self
          TypeMethod
          DescriptionAlias for hs.socket.udp:receiveOne
          Parameters
            Returns
              NotesNone
              Sourceextensions/socket/socket.lua line 243

              Signaturehs.socket.udp:receive([fn]) -> self or nil
              TypeMethod
              DescriptionReads packets from the socket as they arrive.
              Parameters
              Returns
              Notes
              • Results are passed to the callback function, which must be set to use this method.
              • There are two modes of operation for receiving packets: one-at-a-time & continuous.
              • In one-at-a-time mode, you call receiveOne every time you are ready process an incoming UDP packet.
              • Receiving packets one-at-a-time may be better suited for implementing certain state machine code where your state machine may not always be ready to process incoming packets.
              • In continuous mode, the callback is invoked immediately every time incoming udp packets are received.
              • Receiving packets continuously is better suited to real-time streaming applications.
              • You may switch back and forth between one-at-a-time mode and continuous mode.
              • If the socket is currently in one-at-a-time mode, calling this method will switch it to continuous mode.
              ExamplesNone
              Sourceextensions/socket/libsocket_udp.m line 295

              Signaturehs.socket.udp:receiveOne([fn]) -> self or nil
              TypeMethod
              DescriptionReads a single packet from the socket.
              Parameters
              Returns
              Notes
              • Results are passed to the callback function, which must be set to use this method.
              • There are two modes of operation for receiving packets: one-at-a-time & continuous.
              • In one-at-a-time mode, you call receiveOne every time you are ready process an incoming UDP packet.
              • Receiving packets one-at-a-time may be better suited for implementing certain state machine code where your state machine may not always be ready to process incoming packets.
              • In continuous mode, the callback is invoked immediately every time incoming udp packets are received.
              • Receiving packets continuously is better suited to real-time streaming applications.
              • You may switch back and forth between one-at-a-time mode and continuous mode.
              • If the socket is currently in continuous mode, calling this method will switch it to one-at-a-time mode
              ExamplesNone
              Sourceextensions/socket/libsocket_udp.m line 321

              Signaturehs.socket.udp:reusePort([flag]) -> self or nil
              TypeMethod
              DescriptionEnables port reuse on the socket.
              Parameters
              • flag - An optional boolean: true to enable port reuse, false to disable it. Defaults to true.
              Returns
              Notes
              • By default, only one socket can be bound to a given IP address & port at a time.
              • To enable multiple processes to simultaneously bind to the same address & port, you need to enable this functionality in the socket.
              • All processes that wish to use the address & port simultaneously must all enable reuse port on the socket bound to that port.
              • Must be called before binding the socket.
              ExamplesNone
              Sourceextensions/socket/libsocket_udp.m line 452

              Signaturehs.socket.udp:send(message[, host, port][, tag, fn]) -> self
              TypeMethod
              DescriptionSends a packet to the destination address.
              Parameters
              • message - A string containing data to be sent on the socket.
              • host - A string containing the hostname or IP address.
              • port - A port number [1-65535].
              • tag - An optional integer to assist with labeling writes.
              • fn - An optional single-use callback function to execute after sending the packet. The callback receives the tag parameter provided here.
              Returns
              Notes
              • For non-connected sockets, the remote destination is specified for each packet.
              • If the socket has been explicitly connected with connect, only the message parameter and an optional tag and/or write callback can be supplied.
              • Recall that connecting is optional for a UDP socket.
              • For connected sockets, data can only be sent to the connected address.
              ExamplesNone
              Sourceextensions/socket/libsocket_udp.m line 347

              Signaturehs.socket.udp:setBufferSize(size[, version]) -> self
              TypeMethod
              DescriptionSets the maximum size of the buffer that will be allocated for receive operations.
              Parameters
              • size - An number containing the receive buffer size in bytes.
              • version - An optional number containing the IP version for which to set the buffer size. Anything but 4 or 6 else sets the same size for both.
              Returns
              Notes
              • The default maximum size is 9216 bytes.
              • The theoretical maximum size of any IPv4 UDP packet is UINT16_MAX = 65535.
              • The theoretical maximum size of any IPv6 UDP packet is UINT32_MAX = 4294967295.
              • Since the OS notifies us of the size of each received UDP packet, the actual allocated buffer size for each packet is exact.
              • In practice the size of UDP packets is generally much smaller than the max. Most protocols will send and receive packets of only a few bytes, or will set a limit on the size of packets to prevent fragmentation in the IP layer.
              • If you set the buffer size too small, the sockets API in the OS will silently discard any extra data.
              ExamplesNone
              Sourceextensions/socket/libsocket_udp.m line 555

              | | | | --------------------------------------------|-------------------------------------------------------------------------------------| | Signature | hs.socket.udp:setCallback([fn]) -> self | | Type | Method | | Description | Sets the read callback for the socket. | | Parameters |

              • fn - An optional callback function to process data read from the socket. nil or no argument clears the callback. The callback receives 2 parameters: data - The data read from the socket as a string. sockaddr - The sending address as a binary socket address structure. See parseAddress.
              | | Returns | | | Notes |
              • A callback must be set in order to read data from the socket.
              | | Examples | None | | Source | extensions/socket/libsocket_udp.m line 597 |


              Signaturehs.socket.udp:setTimeout(timeout) -> self
              TypeMethod
              DescriptionSets the timeout for the socket operations.
              Parameters
              • timeout - A number containing the timeout duration, in seconds.
              Returns
              Notes
              • If the timeout value is negative, the operations will not use a timeout, which is the default.
              ExamplesNone
              Sourceextensions/socket/libsocket_udp.m line 628

              Signaturehs.socket.udp:write(message[, tag]) -> self
              TypeMethod
              DescriptionAlias for hs.socket.udp:send
              Parameters
                Returns
                  NotesNone
                  Sourceextensions/socket/socket.lua line 249