Files
BR_YKC/4G/code/core/linksocket.lua

159 lines
4.8 KiB
Lua
Raw Normal View History

2026-04-30 17:16:01 +08:00
-- linksocket.lua
-- 功能:管理多个 TCP Socket 连接,支持手动连接/断开,自动重连,数据收发
local log = require "log"
local sys = require "sys"
local socket = require "socket"
-- 服务器配置
local SERVER_IP = "129.211.170.245"
local SERVER_PORT = 9002
2026-04-30 17:16:01 +08:00
local MAX_CLIENTS = 6
-- 客户端状态表
2026-03-31 15:46:04 +08:00
local clients = {}
2026-04-30 17:16:01 +08:00
local keepConnecting = {}
local recvCallback = nil
2026-03-31 15:46:04 +08:00
2026-04-30 17:16:01 +08:00
-- 初始化所有socket槽位
for i = 1, MAX_CLIENTS do
clients[i] = {
2026-03-31 15:46:04 +08:00
id = i,
socket = nil,
connected = false
}
2026-04-30 17:16:01 +08:00
keepConnecting[i] = false
end
-- 发送连接状态响应
local function sendConnStatus(subCmd, socketId, status)
local uart = require "uart"
local frame = string.char(0x55, 0xAA, 0x83, subCmd, socketId, status, 0xAA, 0x55)
uart.write(1, frame)
log.debug("Socket", socketId, "status response, subCmd=", subCmd, "status=", status)
end
-- 设置是否保持连接
local function setKeepConnecting(id, keep)
if id < 1 or id > MAX_CLIENTS then
return false
end
keepConnecting[id] = keep
if not keep and clients[id].connected and clients[id].socket then
clients[id].socket:close()
clients[id].socket = nil
clients[id].connected = false
sendConnStatus(0x02, id, 0)
end
return true
end
2026-03-31 15:46:04 +08:00
2026-04-30 17:16:01 +08:00
-- 发送数据到指定socket
local function sendToSocket(id, data)
if id < 1 or id > MAX_CLIENTS then
log.error("sendToSocket: invalid id", id)
return false
end
if clients[id].connected and clients[id].socket then
clients[id].socket:asyncSend(data)
log.info("Send to socket", id, "len=", #data)
return true
else
log.warn("Socket", id, "not connected, cannot send")
return false
end
end
-- 注册数据接收回调
local function setRecvCallback(cb)
recvCallback = cb
end
-- 为每个socket创建常驻任务
for id = 1, MAX_CLIENTS do
2026-03-31 15:46:04 +08:00
sys.taskInit(function()
2026-04-30 17:16:01 +08:00
local socketId = id
log.debug("Socket", socketId, "control task started")
2026-03-31 15:46:04 +08:00
while true do
2026-04-30 17:16:01 +08:00
while not keepConnecting[socketId] do
sys.wait(1000)
2026-03-31 15:46:04 +08:00
end
2026-04-30 17:16:01 +08:00
while keepConnecting[socketId] do
while not socket.isReady() do
if not keepConnecting[socketId] then break end
sys.wait(1000)
end
if not keepConnecting[socketId] then break end
2026-03-31 15:46:04 +08:00
2026-04-30 17:16:01 +08:00
local sock = socket.tcp()
log.debug("Socket", socketId, "connecting to", SERVER_IP, SERVER_PORT)
local connected = false
while not connected and keepConnecting[socketId] do
connected = sock:connect(SERVER_IP, SERVER_PORT)
if not connected then
log.warn("Socket", socketId, "connect failed, retry in 3s")
sys.wait(3000)
end
end
2026-03-31 15:46:04 +08:00
2026-04-30 17:16:01 +08:00
if not keepConnecting[socketId] then
if sock then sock:close() end
break
end
clients[socketId].socket = sock
clients[socketId].connected = true
log.info("Socket", socketId, "connected")
sendConnStatus(0x01, socketId, 0)
while keepConnecting[socketId] and clients[socketId].connected do
local ok = sock:asyncSelect(60, "recv")
if not ok then
log.warn("Socket", socketId, "connection lost")
break
end
sys.wait(100)
end
if clients[socketId].socket then
clients[socketId].socket:close()
clients[socketId].socket = nil
end
clients[socketId].connected = false
if not keepConnecting[socketId] then
sendConnStatus(0x02, socketId, 0)
break
else
log.info("Socket", socketId, "will reconnect after 3s")
sys.wait(3000)
end
end
end
end)
2026-03-31 15:46:04 +08:00
end
2026-04-30 17:16:01 +08:00
-- 订阅底层Socket接收事件
sys.subscribe("SOCKET_RECV", function(socketId)
2026-03-31 15:46:04 +08:00
for i, client in ipairs(clients) do
2026-04-30 17:16:01 +08:00
if client.socket and client.socket.id == socketId and client.connected then
2026-03-31 15:46:04 +08:00
local data = client.socket:asyncRecv()
2026-04-30 17:16:01 +08:00
if data and #data > 0 then
log.info("Socket", client.id, "received data len=", #data)
if recvCallback then
recvCallback(client.id, data)
end
end
2026-03-31 15:46:04 +08:00
break
end
end
end)
2026-04-30 17:16:01 +08:00
-- 模块接口
local M = {
setKeepConnecting = setKeepConnecting,
sendToSocket = sendToSocket,
setRecvCallback = setRecvCallback,
}
return M