跳转到内容

socket

socket 模块提供了跨平台的网络套接字功能,支持 TCP、UDP 和 Unix 域套接字。这是 xmake 的扩展模块。

提示

使用此模块需要先导入:import("core.base.socket")

socket.tcp

  • 创建 TCP 套接字

函数原型

API

lua
socket.tcp(opt: <table>)

参数说明

参数描述
opt可选。选项参数

用法说明

创建一个 TCP 套接字对象(socket.TCP),默认使用 IPv4。

TCP 是面向连接的、可靠的流式协议,保证数据按序到达,适合大多数网络通信场景。

opt 选项:

  • family:地址族,可选值:
    • socket.IPV4 (1) - IPv4 地址族(默认)
    • socket.IPV6 (2) - IPv6 地址族
lua
-- 创建 IPv4 TCP 套接字
local sock = socket.tcp()

-- 创建 IPv6 TCP 套接字
local sock = socket.tcp({family = socket.IPV6})

socket.udp

  • 创建 UDP 套接字

函数原型

API

lua
socket.udp(opt: <table>)

参数说明

参数描述
opt可选。选项参数

用法说明

创建一个 UDP 套接字对象(socket.UDP),用于无连接的数据报通信。

UDP 是无连接的、不可靠的数据报协议,不保证数据到达和顺序,但延迟低,适合实时通信、广播等场景。

opt 选项:

  • family:地址族,可选值为 socket.IPV4(默认)或 socket.IPV6

UDP 适合需要低延迟、可以容忍少量丢包的场景:

lua
import("core.base.socket")
import("core.base.bytes")

local sock = socket.udp()
sock:bind("127.0.0.1", 9091)

local buff = bytes(8192)
-- 接收数据报
local recv, data, peer_addr, peer_port = sock:recvfrom(buff, 8192)
if recv > 0 then
    print("从", peer_addr, peer_port, "收到", recv, "字节")
end
sock:close()

socket.unix

  • 创建 Unix 域套接字

函数原型

API

lua
socket.unix()

参数说明

此函数不需要参数。

用法说明

创建一个 Unix 域套接字(地址族为 socket.UNIX),用于同一台机器上的进程间通信。

Unix 域套接字使用文件系统路径而不是 IP 地址和端口,性能优于 TCP,因为不需要网络协议栈处理。

仅在 Unix/Linux/macOS 系统上可用。适合本地进程间的高性能通信。

socket.bind

  • 创建并绑定 TCP 套接字

函数原型

API

lua
socket.bind(addr: <string>, port: <number>, opt: <table>)

参数说明

参数描述
addr必需。IP 地址,如 "127.0.0.1" 或 "0.0.0.0"
port必需。端口号
opt可选。选项参数,同 socket.tcp

用法说明

创建 TCP 套接字并绑定到指定地址和端口,通常用于服务端。

完整的 TCP 回显服务器示例:

lua
import("core.base.socket")
import("core.base.bytes")

function main()
    -- 绑定地址并监听
    local server = socket.bind("127.0.0.1", 9091)
    server:listen(20)
    print("服务器监听在 127.0.0.1:9091")
    
    while true do
        -- 接受客户端连接
        local client = server:accept()
        if client then
            print("客户端已连接")
            local buff = bytes(8192)
            
            -- 持续接收和回显数据
            while true do
                local recv, data = client:recv(buff, 8192, {block = true})
                if recv > 0 then
                    print("收到:", data:str())
                    -- 回显数据
                    client:send(data, {block = true})
                else
                    break
                end
            end
            client:close()
        end
    end
    server:close()
end

socket.bind_unix

  • 创建并绑定 Unix 域套接字

函数原型

API

lua
socket.bind_unix(addr: <string>, opt: <table>)

参数说明

参数描述
addr必需。Unix 域套接字路径
opt可选。选项参数

用法说明

创建 Unix 域套接字并绑定到指定路径。

opt 选项:

  • is_abstract:是否使用抽象命名空间(仅 Linux)
lua
import("core.base.socket")

-- 绑定到文件路径
local server = socket.bind_unix("/tmp/my.sock")
server:listen(10)

socket.connect

  • 创建并连接 TCP 套接字

函数原型

API

lua
socket.connect(addr: <string>, port: <number>, opt: <table>)

参数说明

参数描述
addr必需。服务器 IP 地址
port必需。服务器端口号
opt可选。选项参数

用法说明

创建 TCP 套接字并连接到指定地址和端口,用于客户端。

opt 选项:

  • family:地址族
  • timeout:连接超时时间(毫秒)

完整的 TCP 客户端示例:

lua
import("core.base.socket")
import("core.base.bytes")

function main()
    -- 连接到服务器
    local sock = socket.connect("127.0.0.1", 9091)
    if sock then
        print("已连接到服务器")
        local buff = bytes(8192)
        
        -- 发送多条消息
        local count = 0
        while count < 1000 do
            local send = sock:send("hello world..", {block = true})
            if send > 0 then
                -- 接收回显
                sock:recv(buff, 13, {block = true})
                count = count + 1
            else
                break
            end
        end
        print("发送成功,count:", count)
        sock:close()
    end
end

socket.connect_unix

  • 创建并连接 Unix 域套接字

函数原型

API

lua
socket.connect_unix(addr: <string>, opt: <table>)

参数说明

参数描述
addr必需。Unix 域套接字路径
opt可选。选项参数

用法说明

创建 Unix 域套接字并连接到指定路径。

opt 选项:

  • is_abstract:是否使用抽象命名空间(仅 Linux)
  • timeout:连接超时时间

socket:bind

  • 绑定套接字到地址

函数原型

API

lua
socket:bind(addr: <string>, port: <number>)

参数说明

参数描述
addr必需。IP 地址
port必需。端口号

返回值说明

类型描述
number成功返回正数

用法说明

将套接字绑定到指定的 IP 地址和端口。

socket:listen

  • 开始监听连接

函数原型

API

lua
socket:listen(backlog: <number>)

参数说明

参数描述
backlog必需。等待连接队列的最大长度,默认 10

用法说明

使套接字开始监听客户端连接,用于服务端。

必须在 bind 之后、accept 之前调用。

socket:accept

  • 接受客户端连接

函数原型

API

lua
socket:accept(opt: <table>)

参数说明

参数描述
opt可选。选项参数

opt 选项:

  • timeout:超时时间(毫秒),默认 -1(无限等待)

返回值说明

类型描述
socket成功返回客户端套接字对象

用法说明

接受一个客户端连接,返回新的套接字对象用于与客户端通信。默认是非阻塞的,如果没有客户端连接会立即返回。可配合 sock:wait 实现事件驱动:

lua
-- 等待客户端连接
local events = server:wait(socket.EV_ACPT, 5000)
if events == socket.EV_ACPT then
    local client = server:accept()
end

socket:connect

  • 连接到远程地址

函数原型

API

lua
socket:connect(addr: <string>, port: <number>, opt: <table>)

参数说明

参数描述
addr必需。目标 IP 地址
port必需。目标端口号
opt可选。选项参数

用法说明

连接到指定的远程地址和端口。

opt 选项:

  • timeout:连接超时时间(毫秒)

返回值说明

类型描述
number成功返回正数

socket:send

  • 发送数据

函数原型

API

lua
socket:send(data: <string|bytes>, opt: <table>)

参数说明

参数描述
data必需。要发送的数据,可以是字符串或 bytes 对象
opt可选。选项参数

用法说明

通过套接字发送数据。

opt 选项:

  • block:是否阻塞发送,默认 false
  • start:数据起始位置,默认 1
  • last:数据结束位置,默认为数据大小

返回值说明

类型描述
number实际发送的字节数

非阻塞模式可能只发送部分数据,阻塞模式会等待直到所有数据发送完成:

lua
-- 非阻塞发送
local sent = sock:send("hello")

-- 阻塞发送,确保全部发送
local sent = sock:send("hello world", {block = true})
if sent > 0 then
    print("发送了", sent, "字节")
end

socket:recv

  • 接收数据

函数原型

API

lua
socket:recv(buff: <bytes>, size: <number>, opt: <table>)

参数说明

参数描述
buff必需。bytes 缓冲区对象
size必需。要接收的字节数
opt可选。选项参数

用法说明

从套接字接收数据。

opt 选项:

  • block:是否阻塞接收,默认 false
  • timeout:超时时间(毫秒)

返回值说明

类型描述
recv实际接收的字节数
data接收的数据(bytes 对象)
lua
import("core.base.bytes")

local buff = bytes(8192)

-- 非阻塞接收
local recv, data = sock:recv(buff, 1024)

-- 阻塞接收,超时 5 秒
local recv, data = sock:recv(buff, 1024, {block = true, timeout = 5000})
if recv > 0 then
    print("接收到:", data:str())
end

socket:sendto

  • 发送数据报(UDP)

函数原型

API

lua
socket:sendto(data: <string|bytes>, addr: <string>, port: <number>, opt: <table>)

参数说明

参数描述
data必需。要发送的数据,可以是字符串或 bytes 对象
addr必需。目标 IP 地址
port必需。目标端口号
opt可选。选项参数

用法说明

通过 UDP 套接字发送数据报到指定地址。

返回值说明

类型描述
number实际发送的字节数
lua
import("core.base.socket")

local sock = socket.udp()
sock:sendto("hello", "127.0.0.1", 9091)
sock:close()

socket:recvfrom

  • 接收数据报(UDP)

函数原型

API

lua
socket:recvfrom(buff: <bytes>, size: <number>, opt: <table>)

参数说明

参数描述
buff必需。bytes 缓冲区对象
size必需。要接收的字节数
opt可选。选项参数

用法说明

从 UDP 套接字接收数据报,同时获取发送方的地址信息。

opt 选项:

  • block:是否阻塞接收

返回值说明

类型描述
recv实际接收的字节数
data接收的数据(bytes 对象)
peer_addr发送方 IP 地址
peer_port发送方端口号

完整的 UDP 回显服务器示例:

lua
import("core.base.socket")
import("core.base.bytes")

function main()
    local sock = socket.udp()
    sock:bind("127.0.0.1", 9091)
    print("UDP 服务器监听在 127.0.0.1:9091")
    
    local buff = bytes(8192)
    while true do
        print("等待接收数据...")
        local recv, data, peer_addr, peer_port = sock:recvfrom(buff, 8192, {block = true})
        if recv > 0 then
            print("从", peer_addr .. ":" .. peer_port, "收到", recv, "字节:", data:str())
            -- 回显数据
            sock:sendto(data, peer_addr, peer_port)
        end
    end
    sock:close()
end

socket:wait

  • 等待套接字事件

函数原型

API

lua
socket:wait(events: <number>, timeout: <number>)

参数说明

参数描述
events必需。要等待的事件
timeout必需。超时时间(毫秒),-1 表示无限等待

用法说明

等待指定的套接字事件发生。

支持的事件常量:

  • socket.EV_RECV (1):可接收事件
  • socket.EV_SEND (2):可发送事件
  • socket.EV_CONN (2):连接事件(等同于 EV_SEND)
  • socket.EV_ACPT (1):接受连接事件(等同于 EV_RECV)

返回值说明

类型描述
number返回实际发生的事件常量值

用法说明

等待指定的套接字事件发生。在非阻塞模式下实现事件驱动:

lua
-- 等待套接字可读
local events = sock:wait(socket.EV_RECV, 1000)
if events == socket.EV_RECV then
    local recv, data = sock:recv(buff, 1024)
end

-- 等待套接字可写
local events = sock:wait(socket.EV_SEND, 1000)
if events == socket.EV_SEND then
    sock:send("data")
end

socket:close

  • 关闭套接字

函数原型

API

lua
socket:close()

参数说明

此函数不需要参数。

用法说明

关闭套接字并释放资源。使用完套接字后应及时关闭。

socket:ctrl

  • 控制套接字选项

函数原型

API

lua
socket:ctrl(code: <number>, value: <number>)

参数说明

参数描述
code必需。控制码常量
value必需。控制值

用法说明

设置套接字的控制选项,用于调整套接字的缓冲区等参数。

支持的控制码常量:

  • socket.CTRL_SET_RECVBUFF (2):设置接收缓冲区大小(字节)
  • socket.CTRL_SET_SENDBUFF (4):设置发送缓冲区大小(字节)

增大缓冲区可以提高高吞吐量场景下的性能:

lua
-- 设置接收缓冲区为 64KB
sock:ctrl(socket.CTRL_SET_RECVBUFF, 65536)

-- 设置发送缓冲区为 64KB
sock:ctrl(socket.CTRL_SET_SENDBUFF, 65536)

提示

套接字默认是非阻塞的。使用 {block = true} 选项可以启用阻塞模式,简化编程。在协程环境中,套接字会自动与调度器集成,实现异步 I/O。

注意

使用完套接字后记得调用 close() 释放资源。接收数据时需要预先使用 bytes() 创建缓冲区。