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
| Signature | hs.socket.udp.timeout |
|---|---|
| Type | Variable |
| Description | Timeout for the socket operations, in seconds. New [`hs.socket.udp`](#new) objects will be created with this timeout value, but can individually change it with the [`setTimeout`](#setTimeout) method |
| Source | extensions/socket/init.lua |
| Signature | hs.socket.udp.parseAddress(sockaddr) -> table or nil |
|---|---|
| Type | Function |
| Description | Alias for [`hs.socket.parseAddress`](./hs.socket.html#parseAddress) |
| Parameters | |
| Returns | |
| Source | extensions/socket/init.lua |
| Signature | hs.socket.udp.new([fn]) -> hs.socket.udp object |
|---|---|
| Type | Constructor |
| Description | Creates an unconnected asynchronous UDP socket object |
| Parameters |
|
| Returns |
|
| Source | extensions/socket/udp.m |
| Signature | hs.socket.udp.server(port[, fn]) -> hs.socket.udp object |
|---|---|
| Type | Constructor |
| Description | Creates and binds an [`hs.socket.udp`](#new) instance to a port for listening |
| Parameters |
|
| Returns |
|
| Source | extensions/socket/init.lua |
| Signature | hs.socket.udp:broadcast([flag]) -> self or nil |
|---|---|
| Type | Method |
| Description | Enables broadcasting on the underlying socket |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/socket/udp.m |
| Signature | hs.socket.udp:close() -> self |
|---|---|
| Type | Method |
| Description | Immediately closes the underlying socket, freeing the [`hs.socket.udp`](#new) instance for reuse. Any pending send operations are discarded |
| Parameters |
|
| Returns |
|
| Source | extensions/socket/udp.m |
| Signature | hs.socket.udp:closed() -> bool |
|---|---|
| Type | Method |
| Description | Returns the closed status of the [`hs.socket.udp`](#new) instance |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/socket/udp.m |
| Signature | hs.socket.udp:connect(host, port[, fn]) -> self or nil |
|---|---|
| Type | Method |
| Description | Connects an unconnected [`hs.socket.udp`](#new) instance |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/socket/udp.m |
| Signature | hs.socket.udp:connected() -> bool |
|---|---|
| Type | Method |
| Description | Returns the connection status of the [`hs.socket.udp`](#new) instance |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/socket/udp.m |
| Signature | hs.socket.udp:enableIPv(version[, flag]) -> self or nil |
|---|---|
| Type | Method |
| Description | Enables or disables IPv4 or IPv6 on the underlying socket. By default, both are enabled |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/socket/udp.m |
| Signature | hs.socket.udp:info() -> table |
|---|---|
| Type | Method |
| Description | Returns information on the [`hs.socket.udp`](#new) instance |
| Parameters |
|
| Returns |
|
| Source | extensions/socket/udp.m |
| Signature | hs.socket.udp:listen(port) -> self or nil |
|---|---|
| Type | Method |
| Description | Binds an unconnected [`hs.socket.udp`](#new) instance to a port for listening |
| Parameters |
|
| Returns |
|
| Source | extensions/socket/udp.m |
| Signature | hs.socket.udp:pause() -> self |
|---|---|
| Type | Method |
| Description | Suspends reading of packets from the socket. Call one of the receive methods to resume |
| Parameters |
|
| Returns |
|
| Source | extensions/socket/udp.m |
| Signature | hs.socket.udp:preferIPv([version]) -> self |
|---|---|
| Type | Method |
| Description | Sets the preferred IP version: IPv4, IPv6, or neutral (first to resolve) |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/socket/udp.m |
| Signature | hs.socket.udp:read(delimiter[, tag]) -> self |
|---|---|
| Type | Method |
| Description | Alias for [`hs.socket.udp:receive`](#receive) |
| Parameters | |
| Returns | |
| Source | extensions/socket/init.lua |
| Signature | hs.socket.udp:readOne(delimiter[, tag]) -> self |
|---|---|
| Type | Method |
| Description | Alias for [`hs.socket.udp:receiveOne`](#receiveOne) |
| Parameters | |
| Returns | |
| Source | extensions/socket/init.lua |
| Signature | hs.socket.udp:receive([fn]) -> self or nil |
|---|---|
| Type | Method |
| Description | Reads packets from the socket as they arrive. Results are passed to the [callback function](#setCallback), which must be set to use this method |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/socket/udp.m |
| Signature | hs.socket.udp:receiveOne([fn]) -> self or nil |
|---|---|
| Type | Method |
| Description | Reads a single packet from the socket. Results are passed to the [callback function](#setCallback), which must be set to use this method |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/socket/udp.m |
| Signature | hs.socket.udp:reusePort([flag]) -> self or nil |
|---|---|
| Type | Method |
| Description | Enables port reuse on the underlying socket |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/socket/udp.m |
| Signature | hs.socket.udp:send(message, host, port[, tag][, fn]) -> self |
|---|---|
| Type | Method |
| Description | Sends a packet to the destination address |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/socket/udp.m |
| Signature | hs.socket.udp:setBufferSize(size[, version]) -> self |
|---|---|
| Type | Method |
| Description | Sets the maximum size of the buffer that will be allocated for receive operations |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/socket/udp.m |
| Signature | hs.socket.udp:setCallback([fn]) -> self |
|---|---|
| Type | Method |
| Description | Sets the read callback for the [`hs.socket.udp`](#new) instance. Must be set to read data from the socket |
| Parameters |
|
| Returns |
|
| Source | extensions/socket/udp.m |
| Signature | hs.socket.udp:setTimeout(timeout) -> self |
|---|---|
| Type | Method |
| Description | Sets the timeout for the socket operations. If the timeout value is negative, the operations will not use a timeout, which is the default |
| Parameters |
|
| Returns |
|
| Source | extensions/socket/udp.m |
| Signature | hs.socket.udp:write(message[, tag]) -> self |
|---|---|
| Type | Method |
| Description | Alias for [`hs.socket.udp:send`](#send) |
| Parameters | |
| Returns | |
| Source | extensions/socket/init.lua |