socket
The socket module provides cross-platform network socket functionality, supporting TCP, UDP, and Unix domain sockets. This is an extension module of xmake.
TIP
To use this module, you need to import it first: import("core.base.socket")
socket.tcp
- Create a TCP socket
import("core.base.socket")
local sock = socket.tcp()
Creates a TCP socket object (socket.TCP
), using IPv4 by default.
TCP is a connection-oriented, reliable stream protocol that guarantees data arrives in order, suitable for most network communication scenarios.
Parameters:
opt
(optional): Option parametersfamily
: Address family, options:socket.IPV4
(1) - IPv4 address family (default)socket.IPV6
(2) - IPv6 address family
-- Create IPv4 TCP socket
local sock = socket.tcp()
-- Create IPv6 TCP socket
local sock = socket.tcp({family = socket.IPV6})
socket.udp
- Create a UDP socket
import("core.base.socket")
local sock = socket.udp()
Creates a UDP socket object (socket.UDP
) for connectionless datagram communication.
UDP is a connectionless, unreliable datagram protocol that doesn't guarantee data arrival or order, but has low latency, suitable for real-time communication, broadcasting, etc.
Parameters:
opt
(optional): Option parametersfamily
: Address family, can besocket.IPV4
(default) orsocket.IPV6
UDP is suitable for scenarios requiring low latency and can tolerate some packet loss:
import("core.base.socket")
import("core.base.bytes")
local sock = socket.udp()
sock:bind("127.0.0.1", 9091)
local buff = bytes(8192)
-- Receive datagram
local recv, data, peer_addr, peer_port = sock:recvfrom(buff, 8192)
if recv > 0 then
print("Received", recv, "bytes from", peer_addr, peer_port)
end
sock:close()
socket.unix
- Create a Unix domain socket
import("core.base.socket")
local sock = socket.unix()
Creates a Unix domain socket (address family socket.UNIX
) for inter-process communication on the same machine.
Unix domain sockets use filesystem paths instead of IP addresses and ports, offering better performance than TCP because they don't require network protocol stack processing.
Only available on Unix/Linux/macOS systems. Suitable for high-performance local inter-process communication.
socket.bind
- Create and bind a TCP socket
import("core.base.socket")
local sock = socket.bind(addr, port, opt)
Creates a TCP socket and binds it to the specified address and port, typically used for servers.
Parameters:
addr
: IP address, such as"127.0.0.1"
or"0.0.0.0"
port
: Port numberopt
(optional): Option parameters, same as socket.tcp
Complete TCP echo server example:
import("core.base.socket")
import("core.base.bytes")
function main()
-- Bind address and listen
local server = socket.bind("127.0.0.1", 9091)
server:listen(20)
print("Server listening on 127.0.0.1:9091")
while true do
-- Accept client connection
local client = server:accept()
if client then
print("Client connected")
local buff = bytes(8192)
-- Continuously receive and echo data
while true do
local recv, data = client:recv(buff, 8192, {block = true})
if recv > 0 then
print("Received:", data:str())
-- Echo data back
client:send(data, {block = true})
else
break
end
end
client:close()
end
end
server:close()
end
socket.bind_unix
- Create and bind a Unix domain socket
import("core.base.socket")
local sock = socket.bind_unix(addr, opt)
Creates a Unix domain socket and binds it to the specified path.
Parameters:
addr
: Unix domain socket pathopt
(optional): Option parametersis_abstract
: Whether to use abstract namespace (Linux only)
import("core.base.socket")
-- Bind to file path
local server = socket.bind_unix("/tmp/my.sock")
server:listen(10)
socket.connect
- Create and connect a TCP socket
import("core.base.socket")
local sock = socket.connect(addr, port, opt)
Creates a TCP socket and connects to the specified address and port, used for clients.
Parameters:
addr
: Server IP addressport
: Server port numberopt
(optional): Option parametersfamily
: Address familytimeout
: Connection timeout (milliseconds)
Complete TCP client example:
import("core.base.socket")
import("core.base.bytes")
function main()
-- Connect to server
local sock = socket.connect("127.0.0.1", 9091)
if sock then
print("Connected to server")
local buff = bytes(8192)
-- Send multiple messages
local count = 0
while count < 1000 do
local send = sock:send("hello world..", {block = true})
if send > 0 then
-- Receive echo
sock:recv(buff, 13, {block = true})
count = count + 1
else
break
end
end
print("Sent successfully, count:", count)
sock:close()
end
end
socket.connect_unix
- Create and connect a Unix domain socket
import("core.base.socket")
local sock = socket.connect_unix(addr, opt)
Creates a Unix domain socket and connects to the specified path.
Parameters:
addr
: Unix domain socket pathopt
(optional): Option parametersis_abstract
: Whether to use abstract namespace (Linux only)timeout
: Connection timeout
socket:bind
- Bind socket to address
local ok = sock:bind(addr, port)
Binds the socket to the specified IP address and port.
Return value: Returns a positive number on success, -1 and error message on failure.
socket:listen
- Start listening for connections
local ok = sock:listen(backlog)
Makes the socket start listening for client connections, used for servers.
Parameters:
backlog
: Maximum length of the pending connection queue, default 10
Must be called after bind
and before accept
.
socket:accept
- Accept client connection
local client_sock = sock:accept(opt)
Accepts a client connection, returns a new socket object for communicating with the client.
Parameters:
opt
(optional): Option parameterstimeout
: Timeout (milliseconds), default -1 (infinite wait)
Return value: Returns client socket object on success, nil and error message on failure.
Non-blocking by default, returns immediately if no client is connecting. Can be used with sock:wait for event-driven approach:
-- Wait for client connection
local events = server:wait(socket.EV_ACPT, 5000)
if events == socket.EV_ACPT then
local client = server:accept()
end
socket:connect
- Connect to remote address
local ok = sock:connect(addr, port, opt)
Connects to the specified remote address and port.
Parameters:
addr
: Target IP addressport
: Target port numberopt
(optional): Option parameterstimeout
: Connection timeout (milliseconds)
Return value: Returns a positive number on success, -1 and error message on failure.
socket:send
- Send data
local sent = sock:send(data, opt)
Sends data through the socket.
Parameters:
data
: Data to send, can be string or bytes objectopt
(optional): Option parametersblock
: Whether to block sending, default falsestart
: Data start position, default 1last
: Data end position, default is data size
Return value: Actual number of bytes sent, returns -1 on failure.
Non-blocking mode may only send partial data, blocking mode waits until all data is sent:
-- Non-blocking send
local sent = sock:send("hello")
-- Blocking send, ensure all sent
local sent = sock:send("hello world", {block = true})
if sent > 0 then
print("Sent", sent, "bytes")
end
socket:recv
- Receive data
local recv, data = sock:recv(buff, size, opt)
Receives data from the socket.
Parameters:
buff
: bytes buffer objectsize
: Number of bytes to receiveopt
(optional): Option parametersblock
: Whether to block receiving, default falsetimeout
: Timeout (milliseconds)
Return values:
recv
: Actual number of bytes received, returns -1 on failuredata
: Received data (bytes object)
import("core.base.bytes")
local buff = bytes(8192)
-- Non-blocking receive
local recv, data = sock:recv(buff, 1024)
-- Blocking receive, timeout 5 seconds
local recv, data = sock:recv(buff, 1024, {block = true, timeout = 5000})
if recv > 0 then
print("Received:", data:str())
end
socket:sendto
- Send datagram (UDP)
local sent = sock:sendto(data, addr, port, opt)
Sends a datagram to the specified address via UDP socket.
Parameters:
data
: Data to send, can be string or bytes objectaddr
: Target IP addressport
: Target port numberopt
(optional): Option parameters
Return value: Actual number of bytes sent, returns -1 on failure.
import("core.base.socket")
local sock = socket.udp()
sock:sendto("hello", "127.0.0.1", 9091)
sock:close()
socket:recvfrom
- Receive datagram (UDP)
local recv, data, peer_addr, peer_port = sock:recvfrom(buff, size, opt)
Receives a datagram from the UDP socket and gets the sender's address information.
Parameters:
buff
: bytes buffer objectsize
: Number of bytes to receiveopt
(optional): Option parametersblock
: Whether to block receiving
Return values:
recv
: Actual number of bytes receiveddata
: Received data (bytes object)peer_addr
: Sender's IP addresspeer_port
: Sender's port number
Complete UDP echo server example:
import("core.base.socket")
import("core.base.bytes")
function main()
local sock = socket.udp()
sock:bind("127.0.0.1", 9091)
print("UDP server listening on 127.0.0.1:9091")
local buff = bytes(8192)
while true do
print("Waiting to receive data...")
local recv, data, peer_addr, peer_port = sock:recvfrom(buff, 8192, {block = true})
if recv > 0 then
print("Received", recv, "bytes from", peer_addr .. ":" .. peer_port .. ":", data:str())
-- Echo data back
sock:sendto(data, peer_addr, peer_port)
end
end
sock:close()
end
socket:wait
- Wait for socket events
local events = sock:wait(events, timeout)
Waits for specified socket events to occur.
Parameters:
events
: Events to wait for, supports the following event constants:socket.EV_RECV
(1): Receivable eventsocket.EV_SEND
(2): Sendable eventsocket.EV_CONN
(2): Connection event (equivalent to EV_SEND)socket.EV_ACPT
(1): Accept connection event (equivalent to EV_RECV)
timeout
: Timeout (milliseconds), -1 means infinite wait
Return value: Returns the actual event constant value that occurred.
Implementing event-driven in non-blocking mode:
-- Wait for socket to be readable
local events = sock:wait(socket.EV_RECV, 1000)
if events == socket.EV_RECV then
local recv, data = sock:recv(buff, 1024)
end
-- Wait for socket to be writable
local events = sock:wait(socket.EV_SEND, 1000)
if events == socket.EV_SEND then
sock:send("data")
end
socket:close
- Close socket
sock:close()
Closes the socket and releases resources. Sockets should be closed promptly after use.
socket:ctrl
- Control socket options
local ok = sock:ctrl(code, value)
Sets socket control options to adjust socket parameters such as buffer sizes.
Supported control code constants:
socket.CTRL_SET_RECVBUFF
(2): Set receive buffer size (bytes)socket.CTRL_SET_SENDBUFF
(4): Set send buffer size (bytes)
Increasing buffer sizes can improve performance in high-throughput scenarios:
-- Set receive buffer to 64KB
sock:ctrl(socket.CTRL_SET_RECVBUFF, 65536)
-- Set send buffer to 64KB
sock:ctrl(socket.CTRL_SET_SENDBUFF, 65536)
TIP
Sockets are non-blocking by default. Use the {block = true}
option to enable blocking mode for simpler programming. In a coroutine environment, sockets automatically integrate with the scheduler for asynchronous I/O.
WARNING
Remember to call close()
after using the socket to release resources. A bytes buffer must be created using bytes()
before receiving data.