Building a Server
Accept incoming connections.
Building a Server is a free Lua Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Lua Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Server Lifecycle
A TCP server binds to an address, listens for connections, then loops accepting and serving clients.
In LuaSocket you create a master with socket.tcp(), turn it into a listening server with bind/listen, and pull clients off the queue with accept.
local socket = require("socket")
local server = assert(socket.tcp())Binding to a Port
server:bind(host, port) reserves a local address. Use "*" or "0.0.0.0" to accept connections on every interface, or "127.0.0.1" for local only.
Bind fails with "address already in use" if another process holds the port.
server:setoption("reuseaddr", true)
local ok, err = server:bind("*", 8080)
if not ok then error("bind failed: " .. err) endListening for Clients
server:listen(backlog) marks the socket passive and starts queuing incoming handshakes. The backlog is the maximum number of pending connections.
The shortcut socket.bind(host, port, backlog) performs bind and listen in one call, returning a ready server object.
local socket = require("socket")
local server = assert(socket.bind("*", 8080, 32))
print("listening on", server:getsockname())Accepting a Connection
server:accept() blocks until a client connects, then returns a brand-new TCP client object for that peer. The server socket itself keeps listening.
On a timed-out server socket, accept returns nil, "timeout", which lets you interleave other work.
local client, err = server:accept()
if client then
print("client from", client:getpeername())
endServing One Client
After accept, treat the returned object exactly like a client socket: receive requests and send responses.
Give the per-client socket its own timeout so one slow client cannot stall the whole server.
client:settimeout(10)
local line = client:receive("*l")
if line then client:send(line .. "\n") end
client:close()The Accept Loop
A classic iterative server loops forever: accept a client, serve it, close it, repeat. This handles one client at a time.
It is simple and correct but cannot serve concurrent clients, since a slow request blocks everyone behind it.
while true do
local c = server:accept()
if c then
local msg = c:receive("*l")
if msg then c:send(msg .. "\r\n") end
c:close()
end
endA Minimal Echo Server
Putting it together, an echo server binds, listens, then loops echoing each client's first line back.
This is the smallest complete LuaSocket server and a useful target for the client you built earlier.
local socket = require("socket")
local s = assert(socket.bind("*", 8080))
while true do
local c = s:accept()
c:send((c:receive("*l") or "") .. "\r\n")
c:close()
endConcurrency with select
To serve many clients at once without threads, use socket.select. It returns the sockets that are ready to read, including the listening server when a new client waits.
You manage a table of active clients and process only those that have data, keeping a single-threaded event loop responsive.
local readable = socket.select(watch, nil, 1)
for _, sock in ipairs(readable) do
if sock == server then
table.insert(watch, server:accept())
end
endNon-Blocking Accept
Set server:settimeout(0) so accept never blocks. Pair it with select so you only call accept when the listener is actually readable.
This is the foundation of a scalable single-process server that multiplexes hundreds of connections.
server:settimeout(0)
local ready = socket.select({server}, nil, 5)
if #ready > 0 then
local c = server:accept()
endHandling Client Errors
Clients disconnect abruptly. When receive returns nil, "closed" or a partial buffer, drop that client from your watch table and close its socket.
Never let one broken connection take down the accept loop; isolate each client's failures.
local data, err = client:receive("*l")
if err == "closed" then
client:close()
remove_from_watch(client)
endClean Shutdown
On shutdown, stop accepting, close every active client socket, then close the listening server to release the port.
Setting reuseaddr at bind time lets you restart immediately without waiting out the TCP TIME_WAIT period.
for _, c in ipairs(clients) do c:close() end
server:close()
print("server stopped")Quick Check
Pick the call sequence that turns a fresh master socket into a working listener.
Recap
You built a TCP server: bind with reuseaddr, listen with a backlog, and loop on accept to serve clients.
You saw the simple iterative loop, then scaled it with socket.select for non-blocking concurrency, plus error isolation and clean shutdown. Next you will move up to HTTP.
Frequently asked questions
Is the “Building a Server” lesson free?
Yes — the full text of “Building a Server” is free to read here on the web, and the Lua Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Lua Academy course, upgrade to CoddyKit PRO.
What will I learn in “Building a Server”?
Accept incoming connections. You practise Lua Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Lua Academy?
No prior experience is required. Lua Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Building a Server” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Lua Academy lesson?
Yes. Every Lua Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- TCP Basics
- Building a Client
- Building a Server
- HTTP Requests