Building a Client
Request data from a server.
Building a Client is a free Lua Academy lesson on CoddyKit — lesson 2 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.
Client Lifecycle
A TCP client follows a clear lifecycle: create a socket, connect to a server, exchange data, then close.
In LuaSocket each step is one method call, and each can fail. A well-written client checks every return value and cleans up its socket on any error path.
local socket = require("socket")
local client = assert(socket.tcp())Connecting Safely
Set a connect timeout before calling connect so a dead host does not hang your program. A few seconds is typical.
If connect returns nil, log the error and abort. Never assume the handshake succeeded.
client:settimeout(5)
local ok, err = client:connect("127.0.0.1", 8080)
if not ok then
client:close()
error("connect failed: " .. err)
endUsing socket.connect
For the common case, socket.connect(host, port) wraps creation and connection. It returns a ready client object or nil and an error.
This is concise but gives you no chance to set a timeout before the handshake, so prefer the explicit form for unreliable networks.
local socket = require("socket")
local client, err = socket.connect("example.com", 13)
if not client then error(err) endSending a Request
Once connected, write your request bytes with send. Many text protocols delimit lines with carriage-return + newline (\r\n).
Because TCP is a stream, terminate each logical message clearly so the server knows where it ends.
local msg = "PING\r\n"
local sent, err = client:send(msg)
if not sent then error("send failed: " .. err) endReading a Line Reply
For line-based protocols, loop reading with the "*l" pattern. Each call returns one line without its terminator.
On nil, inspect the error: "closed" means the server hung up, while "timeout" means no data arrived in time.
client:settimeout(5)
local line, err = client:receive("*l")
if line then
print("server said:", line)
else
print("recv error:", err)
endReading a Whole Response
Request/response protocols often read everything until the server closes. Use "*a" to capture the full body.
If you half-close your send side first with shutdown("send"), the server sees end-of-input and can finish its reply.
client:send("GET DATA\r\n")
client:shutdown("send")
local body, err = client:receive("*a")
print(#(body or ""), "bytes received")Fixed-Length Framing
Binary protocols often prefix each message with its length. Read the length header first, then read exactly that many bytes.
Passing a number to receive blocks until that count arrives or the socket errors, giving you precise framing over the byte stream.
local header = client:receive(4)
local len = string.unpack(">I4", header)
local payload = client:receive(len)A Complete Echo Client
Here is the whole flow: connect, send a line, read the echoed line, and close. This is the canonical LuaSocket client shape.
Notice every fallible call is guarded with assert for brevity, but a real client would handle errors gracefully.
local socket = require("socket")
local c = assert(socket.connect("127.0.0.1", 8080))
assert(c:send("hello\r\n"))
print(c:receive("*l"))
c:close()Handling Disconnects
Servers can drop connections at any time. A send to a closed peer may return nil, "closed", and receive returns the partial data plus the error.
Treat "closed" as a normal terminal state, not a crash. Reconnect logic belongs in a retry wrapper around the client.
local data, err, partial = client:receive("*a")
if err == "closed" then
print("peer closed, got", #partial, "bytes")
endNon-Blocking Clients
Set the timeout to 0 for a fully non-blocking client. Calls then return immediately, signalling "timeout" when no progress is possible.
Combine this with socket.select to wait efficiently for readiness across many sockets without busy-looping.
client:settimeout(0)
local r = socket.select({client}, nil, 5)
if #r > 0 then print(client:receive("*l")) endResolving Hostnames
If you connect by hostname, LuaSocket resolves it for you. To inspect or cache the resolution, call socket.dns.toip or socket.dns.getaddrinfo yourself.
Resolving once and connecting by IP avoids repeated DNS lookups in a tight reconnect loop.
local socket = require("socket")
local ip = assert(socket.dns.toip("example.com"))
local c = assert(socket.connect(ip, 80))Quick Check
Choose the correct way to read everything a server sends until it closes.
Recap
You built a TCP client end to end: connect with a timeout, frame and send requests, read line, byte-count, or whole-stream responses, and close cleanly.
You also saw disconnect handling, non-blocking mode with select, and DNS caching. Next you will write the server side that answers these clients.
Frequently asked questions
Is the “Building a Client” lesson free?
Yes — the full text of “Building a Client” 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 Client”?
Request data from a server. 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 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Building a Client” 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