Lua TCP聊天室服务器无法处理多客户端连接问题求助
Lua TCP聊天室服务器:多客户端连接问题解决
问题描述
用Lua编写的TCP聊天室服务器支持单个客户端正常连接,但新客户端必须等待已有客户端退出才能成功接入。
问题原因
原代码中处理客户端消息的handle函数使用了阻塞式的client:receive(),再加上Lua协程是协作式调度的特性:当第一个客户端的协程进入receive()阻塞后,不会主动让出CPU,导致主循环的accept()逻辑虽设置了短超时,但协程无法切换回主循环处理新连接请求,最终服务器无法接受新客户端。
修复方案
使用LuaSocket的socket.select函数实现多路IO复用,同时监听服务器的连接请求和所有客户端的消息输入,避免阻塞并同时处理多个客户端。
修复后的server.lua
require('socket') local server = assert(socket.bind('localhost', 69420)) server:settimeout(0) -- 设置服务器socket为非阻塞 local clients = {} -- 广播消息给所有客户端 local function broadcast(message) if not message then return end for _, client in pairs(clients) do local ok, err = client:send(message .. '\n') -- 处理发送失败的客户端(已断开) if err then client:close() table.remove(clients, _) end end end -- 主循环:用select处理多路IO local function mainLoop() print("localhost server listening on port 69420... nice") while true do -- 准备要监听的读socket:服务器socket + 所有客户端socket local readSockets = {server} for _, client in pairs(clients) do table.insert(readSockets, client) end -- 等待可读事件,无超时(也可设置超时比如1秒) local readable, _, err = socket.select(readSockets, nil) if err then print("select error:", err) break end -- 处理每个可读的socket for _, sock in pairs(readable) do -- 如果是服务器socket,说明有新连接 if sock == server then local client = server:accept() if client then client:settimeout(0) -- 设置客户端socket为非阻塞 table.insert(clients, client) print("a new client entered") broadcast("a new client has joined us") end else -- 如果是客户端socket,读取消息 local buff, err = sock:receive() if err then -- 客户端断开或出错 print("client error/disconnected:", err) sock:close() -- 从客户端列表移除 for i, c in pairs(clients) do if c == sock then table.remove(clients, i) broadcast("a client has left") break end end else -- 广播收到的消息 print("received:", buff) broadcast(buff) end end end end end mainLoop()
客户端代码无需修改(client.lua保持原样)
关键改动说明
- 设置所有socket为非阻塞:服务器socket和客户端socket都调用
settimeout(0),避免单个IO操作阻塞整个进程。 - 使用
socket.select管理多路IO:一次性监听所有需要处理的socket,当有socket可读时(新连接或客户端消息)再进行处理,避免无效轮询和阻塞。 - 完善客户端断开处理:当客户端出错或断开时,及时关闭socket并从列表中移除,同时广播离开消息。
内容的提问来源于stack exchange,提问作者danilogames220
相关产品推荐
相关产品推荐

