skynet中的client.socket库函数详解
目录
- 1. connect
- 2. recv
- 3. send
- 4. shutdown
- 5. close
- 6. usleep
- 关键机制与注意事项
- 使用示例
在Skynet框架中,client.socket
模块封装了底层的网络操作,提供了Lua层与C层交互的接口。以下是其核心函数的详细解析:
1. connect
函数原型: socket.connect(地址, 端口)
作用: 发起TCP连接请求。
参数:
地址
: 目标服务器IP(字符串,如"127.0.0.1"
)端口
: 目标端口(整数,如80
)
行为:
- 非阻塞连接:连接操作异步执行,立即返回连接状态或请求ID。
- 回调机制:连接结果通过Skynet消息通知服务,需注册
socket.open
事件处理。 - 示例:
local id = socket.connect("127.0.0.1", 8000) -- id为连接标识符,后续操作需使用此ID
2. recv
函数原型: socket.recv(id [, 模式])
作用: 从socket接收数据。 非阻塞的,没收到直接返回两个nil
参数:
id
: 连接标识符模式
(可选): 接收模式,默认"*l"
(行模式)或"*a"
(全部数据)
返回值:
- 成功: 返回数据字符串
- 失败: 返回
nil, 错误信息
- 非阻塞: 不管是否读取到,直接返回
nil,nil
示例
while true dolocal data, err = socket.recv(id,"l")if data == "" then --断开连接返回的是2个空字符串socket.shutdown(id,"rw")breakendif not data then goto continue end --非阻塞读取没读到返回nil,nilprint("收到数据:", data)socket.send(id,"return "..data.."\n")::continue::
end
3. send
函数原型: socket.send(id, 数据)
作用: 发送数据到远程主机。
参数:
id
: 连接标识符数据
: 待发送的字符串
返回值:
- 成功: 返回
true
- 失败: 返回
nil, 错误信息
行为:
- 非阻塞发送:数据写入内核发送缓冲区后立即返回。
- 流量控制:缓冲区满时可能部分发送,需处理背压(通过返回错误或重试)。
- 示例:
local ok, err = socket.send(id, "Hello World") if not ok thenprint("发送失败:", err) end
4. shutdown
函数原型: socket.shutdown(id [, 模式])
作用: 关闭连接的单向通信。
参数:
id
: 连接标识符模式
(可选):"w"
(关闭写端,默认)或"rw"
(双向关闭)
行为:
- 优雅关闭:发送FIN包通知对端,允许接收残留数据。
- 资源释放:关闭写端后仍可读取数据,避免资源泄漏。
- 示例:
socket.shutdown(id, "w") -- 停止发送,仍可接收数据
5. close
函数原型: socket.close(id)
作用: 强制关闭socket连接。
参数: id
(连接标识符)
行为:
- 立即释放:关闭socket并回收相关资源。
- 不可逆操作:后续所有操作(send/recv)均会失败。
- 示例:
socket.close(id) -- 终止连接
6. usleep
函数原型: socket.usleep(微秒)
作用: 挂起当前协程指定微秒数。
参数: 微秒
(整数,如 1000000
表示1秒)
行为:
- 非阻塞休眠:利用Skynet的定时器机制,协程让出CPU。
- 精度限制:实际休眠时间受系统调度影响,最小单位通常为毫秒级。
- 示例:
socket.usleep(500000) -- 休眠0.5秒
关键机制与注意事项
- 协程模型:所有函数均基于协程实现非阻塞,避免阻塞整个服务。
- 事件驱动:连接成功、数据到达等事件通过Skynet消息队列传递。
- 错误处理:
- 连接超时需自行实现(如结合
skynet.timeout
)。 - 网络异常时,recv/send返回错误码(如
ECONNRESET
)。
- 连接超时需自行实现(如结合
- 资源管理:确保
close
调用防止socket泄漏,尤其在异常路径。
使用示例
local socket = require "client.socket"-- 发起连接
local id = socket.connect("192.168.1.8", 8080)
if not id then error("连接失败") end-- 发送数据
socket.send(id, "GET / HTTP/1.1\r\nHost: localhost\r\n\r\n")-- 接收响应
while true dolocal data, err = socket.recv(id,"l")if data == "" thenbreakendif not data then goto continue endprint("收到数据:", data)socket.send(id,"return "..data.."\n")::continue::
end-- 关闭连接
socket.shutdown(id,"rw")
通过合理组合这些函数,可构建高性能的网络客户端,适应Skynet服务间的通信需求。