socket
socket 模块提供了跨平台的网络套接字功能,支持 TCP、UDP 和 Unix 域套接字。这是 xmake 的扩展模块。
提示
使用此模块需要先导入:import("core.base.socket")
socket.tcp
- 创建 TCP 套接字
函数原型
API
socket.tcp(opt: <table>)参数说明
| 参数 | 描述 |
|---|---|
| opt | 可选。选项参数 |
用法说明
创建一个 TCP 套接字对象(socket.TCP),默认使用 IPv4。
TCP 是面向连接的、可靠的流式协议,保证数据按序到达,适合大多数网络通信场景。
opt 选项:
family:地址族,可选值:socket.IPV4(1) - IPv4 地址族(默认)socket.IPV6(2) - IPv6 地址族
-- 创建 IPv4 TCP 套接字
local sock = socket.tcp()
-- 创建 IPv6 TCP 套接字
local sock = socket.tcp({family = socket.IPV6})socket.udp
- 创建 UDP 套接字
函数原型
API
socket.udp(opt: <table>)参数说明
| 参数 | 描述 |
|---|---|
| opt | 可选。选项参数 |
用法说明
创建一个 UDP 套接字对象(socket.UDP),用于无连接的数据报通信。
UDP 是无连接的、不可靠的数据报协议,不保证数据到达和顺序,但延迟低,适合实时通信、广播等场景。
opt 选项:
family:地址族,可选值为socket.IPV4(默认)或socket.IPV6
UDP 适合需要低延迟、可以容忍少量丢包的场景:
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
socket.unix()参数说明
此函数不需要参数。
用法说明
创建一个 Unix 域套接字(地址族为 socket.UNIX),用于同一台机器上的进程间通信。
Unix 域套接字使用文件系统路径而不是 IP 地址和端口,性能优于 TCP,因为不需要网络协议栈处理。
仅在 Unix/Linux/macOS 系统上可用。适合本地进程间的高性能通信。
socket.bind
- 创建并绑定 TCP 套接字
函数原型
API
socket.bind(addr: <string>, port: <number>, opt: <table>)参数说明
| 参数 | 描述 |
|---|---|
| addr | 必需。IP 地址,如 "127.0.0.1" 或 "0.0.0.0" |
| port | 必需。端口号 |
| opt | 可选。选项参数,同 socket.tcp |
用法说明
创建 TCP 套接字并绑定到指定地址和端口,通常用于服务端。
完整的 TCP 回显服务器示例:
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()
endsocket.bind_unix
- 创建并绑定 Unix 域套接字
函数原型
API
socket.bind_unix(addr: <string>, opt: <table>)参数说明
| 参数 | 描述 |
|---|---|
| addr | 必需。Unix 域套接字路径 |
| opt | 可选。选项参数 |
用法说明
创建 Unix 域套接字并绑定到指定路径。
opt 选项:
is_abstract:是否使用抽象命名空间(仅 Linux)
import("core.base.socket")
-- 绑定到文件路径
local server = socket.bind_unix("/tmp/my.sock")
server:listen(10)socket.connect
- 创建并连接 TCP 套接字
函数原型
API
socket.connect(addr: <string>, port: <number>, opt: <table>)参数说明
| 参数 | 描述 |
|---|---|
| addr | 必需。服务器 IP 地址 |
| port | 必需。服务器端口号 |
| opt | 可选。选项参数 |
用法说明
创建 TCP 套接字并连接到指定地址和端口,用于客户端。
opt 选项:
family:地址族timeout:连接超时时间(毫秒)
完整的 TCP 客户端示例:
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
endsocket.connect_unix
- 创建并连接 Unix 域套接字
函数原型
API
socket.connect_unix(addr: <string>, opt: <table>)参数说明
| 参数 | 描述 |
|---|---|
| addr | 必需。Unix 域套接字路径 |
| opt | 可选。选项参数 |
用法说明
创建 Unix 域套接字并连接到指定路径。
opt 选项:
is_abstract:是否使用抽象命名空间(仅 Linux)timeout:连接超时时间
socket:bind
- 绑定套接字到地址
函数原型
API
socket:bind(addr: <string>, port: <number>)参数说明
| 参数 | 描述 |
|---|---|
| addr | 必需。IP 地址 |
| port | 必需。端口号 |
返回值说明
| 类型 | 描述 |
|---|---|
| number | 成功返回正数 |
用法说明
将套接字绑定到指定的 IP 地址和端口。
socket:listen
- 开始监听连接
函数原型
API
socket:listen(backlog: <number>)参数说明
| 参数 | 描述 |
|---|---|
| backlog | 必需。等待连接队列的最大长度,默认 10 |
用法说明
使套接字开始监听客户端连接,用于服务端。
必须在 bind 之后、accept 之前调用。
socket:accept
- 接受客户端连接
函数原型
API
socket:accept(opt: <table>)参数说明
| 参数 | 描述 |
|---|---|
| opt | 可选。选项参数 |
opt 选项:
timeout:超时时间(毫秒),默认 -1(无限等待)
返回值说明
| 类型 | 描述 |
|---|---|
| socket | 成功返回客户端套接字对象 |
用法说明
接受一个客户端连接,返回新的套接字对象用于与客户端通信。默认是非阻塞的,如果没有客户端连接会立即返回。可配合 sock:wait 实现事件驱动:
-- 等待客户端连接
local events = server:wait(socket.EV_ACPT, 5000)
if events == socket.EV_ACPT then
local client = server:accept()
endsocket:connect
- 连接到远程地址
函数原型
API
socket:connect(addr: <string>, port: <number>, opt: <table>)参数说明
| 参数 | 描述 |
|---|---|
| addr | 必需。目标 IP 地址 |
| port | 必需。目标端口号 |
| opt | 可选。选项参数 |
用法说明
连接到指定的远程地址和端口。
opt 选项:
timeout:连接超时时间(毫秒)
返回值说明
| 类型 | 描述 |
|---|---|
| number | 成功返回正数 |
socket:send
- 发送数据
函数原型
API
socket:send(data: <string|bytes>, opt: <table>)参数说明
| 参数 | 描述 |
|---|---|
| data | 必需。要发送的数据,可以是字符串或 bytes 对象 |
| opt | 可选。选项参数 |
用法说明
通过套接字发送数据。
opt 选项:
block:是否阻塞发送,默认 falsestart:数据起始位置,默认 1last:数据结束位置,默认为数据大小
返回值说明
| 类型 | 描述 |
|---|---|
| number | 实际发送的字节数 |
非阻塞模式可能只发送部分数据,阻塞模式会等待直到所有数据发送完成:
-- 非阻塞发送
local sent = sock:send("hello")
-- 阻塞发送,确保全部发送
local sent = sock:send("hello world", {block = true})
if sent > 0 then
print("发送了", sent, "字节")
endsocket:recv
- 接收数据
函数原型
API
socket:recv(buff: <bytes>, size: <number>, opt: <table>)参数说明
| 参数 | 描述 |
|---|---|
| buff | 必需。bytes 缓冲区对象 |
| size | 必需。要接收的字节数 |
| opt | 可选。选项参数 |
用法说明
从套接字接收数据。
opt 选项:
block:是否阻塞接收,默认 falsetimeout:超时时间(毫秒)
返回值说明
| 类型 | 描述 |
|---|---|
| recv | 实际接收的字节数 |
| data | 接收的数据(bytes 对象) |
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())
endsocket:sendto
- 发送数据报(UDP)
函数原型
API
socket:sendto(data: <string|bytes>, addr: <string>, port: <number>, opt: <table>)参数说明
| 参数 | 描述 |
|---|---|
| data | 必需。要发送的数据,可以是字符串或 bytes 对象 |
| addr | 必需。目标 IP 地址 |
| port | 必需。目标端口号 |
| opt | 可选。选项参数 |
用法说明
通过 UDP 套接字发送数据报到指定地址。
返回值说明
| 类型 | 描述 |
|---|---|
| number | 实际发送的字节数 |
import("core.base.socket")
local sock = socket.udp()
sock:sendto("hello", "127.0.0.1", 9091)
sock:close()socket:recvfrom
- 接收数据报(UDP)
函数原型
API
socket:recvfrom(buff: <bytes>, size: <number>, opt: <table>)参数说明
| 参数 | 描述 |
|---|---|
| buff | 必需。bytes 缓冲区对象 |
| size | 必需。要接收的字节数 |
| opt | 可选。选项参数 |
用法说明
从 UDP 套接字接收数据报,同时获取发送方的地址信息。
opt 选项:
block:是否阻塞接收
返回值说明
| 类型 | 描述 |
|---|---|
| recv | 实际接收的字节数 |
| data | 接收的数据(bytes 对象) |
| peer_addr | 发送方 IP 地址 |
| peer_port | 发送方端口号 |
完整的 UDP 回显服务器示例:
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()
endsocket:wait
- 等待套接字事件
函数原型
API
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 | 返回实际发生的事件常量值 |
用法说明
等待指定的套接字事件发生。在非阻塞模式下实现事件驱动:
-- 等待套接字可读
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")
endsocket:close
- 关闭套接字
函数原型
API
socket:close()参数说明
此函数不需要参数。
用法说明
关闭套接字并释放资源。使用完套接字后应及时关闭。
socket:ctrl
- 控制套接字选项
函数原型
API
socket:ctrl(code: <number>, value: <number>)参数说明
| 参数 | 描述 |
|---|---|
| code | 必需。控制码常量 |
| value | 必需。控制值 |
用法说明
设置套接字的控制选项,用于调整套接字的缓冲区等参数。
支持的控制码常量:
socket.CTRL_SET_RECVBUFF(2):设置接收缓冲区大小(字节)socket.CTRL_SET_SENDBUFF(4):设置发送缓冲区大小(字节)
增大缓冲区可以提高高吞吐量场景下的性能:
-- 设置接收缓冲区为 64KB
sock:ctrl(socket.CTRL_SET_RECVBUFF, 65536)
-- 设置发送缓冲区为 64KB
sock:ctrl(socket.CTRL_SET_SENDBUFF, 65536)提示
套接字默认是非阻塞的。使用 {block = true} 选项可以启用阻塞模式,简化编程。在协程环境中,套接字会自动与调度器集成,实现异步 I/O。
注意
使用完套接字后记得调用 close() 释放资源。接收数据时需要预先使用 bytes() 创建缓冲区。