Создание сервера
Принимайте входящие соединения.
«Создание сервера» — бесплатный урок Lua Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Lua Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Lua Academy содержит 4 уроков всего.
Жизненный цикл сервера
TCP-сервер выполняет bind для адреса, начинает прослушивание подключений, а затем в цикле принимает и обслуживает клиентов.
В LuaSocket Вы создаёте главный сокет с помощью socket.tcp(), превращаете его в сервер, прослушивающий подключения, с помощью bind/listen и извлекаете клиентов из очереди вызовом accept.
local socket = require("socket")
local server = assert(socket.tcp())Привязка к порту
server:bind(host, port) резервирует локальный адрес. Используйте "*" или "0.0.0.0", чтобы принимать подключения на каждом интерфейсе, либо "127.0.0.1" — только для локальных подключений.
Операция bind завершается ошибкой "address already in use", если другой процесс уже занял порт.
server:setoption("reuseaddr", true)
local ok, err = server:bind("*", 8080)
if not ok then error("bind failed: " .. err) endОжидание подключений клиентов
server:listen(backlog) переводит сокет в пассивный режим и начинает ставить входящие рукопожатия в очередь. Параметр backlog задаёт максимальное число ожидающих подключений.
Сокращённая форма socket.bind(host, port, backlog) выполняет bind и listen одним вызовом, возвращая готовый серверный объект.
local socket = require("socket")
local server = assert(socket.bind("*", 8080, 32))
print("listening on", server:getsockname())Принятие подключения
server:accept() блокирует выполнение до подключения клиента, после чего возвращает совершенно новый объект TCP-клиента для этого узла. Сам серверный сокет продолжает прослушивание.
На серверном сокете с установленным тайм-аутом accept возвращает nil, "timeout", что позволяет чередовать ожидание с другой работой.
local client, err = server:accept()
if client then
print("client from", client:getpeername())
endОбслуживание одного клиента
После принятия подключения рассматривайте возвращённый объект так же, как клиентский сокет: запрашивайте данные с помощью receive и отправляйте ответы с помощью send.
Задайте для сокета отдельного клиента собственный тайм-аут, чтобы один медленный клиент не остановил работу всего сервера.
client:settimeout(10)
local line = client:receive("*l")
if line then client:send(line .. "\n") end
client:close()Цикл принятия подключений
Классический итеративный сервер работает в бесконечном цикле: принять клиента, обслужить его, закрыть соединение и повторить. Он обрабатывает по одному клиенту за раз.
Это простой и корректный подход, но он не может обслуживать клиентов одновременно, поскольку медленный запрос блокирует всех следующих за ним.
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
endМинимальный эхо-сервер
Если собрать всё вместе, эхо-сервер выполняет bind, начинает прослушивание, а затем в цикле возвращает каждому клиенту его первую строку.
Это самый маленький полноценный сервер LuaSocket и полезная цель для созданного ранее клиента.
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()
endПараллельная обработка с помощью select
Чтобы одновременно обслуживать множество клиентов без потоков, используйте socket.select. Он возвращает сокеты, готовые к чтению, включая серверный сокет прослушивания, когда ожидает новое подключение.
Вы управляете таблицей активных клиентов и обрабатываете только те сокеты, в которых есть данные, поддерживая отзывчивость однопоточного цикла обработки событий.
local readable = socket.select(watch, nil, 1)
for _, sock in ipairs(readable) do
if sock == server then
table.insert(watch, server:accept())
end
endНеблокирующее принятие подключений
Задайте server:settimeout(0), чтобы операция принятия никогда не блокировала выполнение. Сочетайте её с select, чтобы вызывать принятие только тогда, когда сокет прослушивания действительно готов к чтению.
Это основа масштабируемого сервера в одном процессе, который мультиплексирует сотни соединений.
server:settimeout(0)
local ready = socket.select({server}, nil, 5)
if #ready > 0 then
local c = server:accept()
endОбработка ошибок клиентов
Клиенты могут внезапно отключиться. Если receive возвращает nil, "closed" или частичный буфер, удалите этого клиента из таблицы отслеживаемых соединений и закройте его сокет.
Никогда не позволяйте одному неисправному соединению остановить цикл принятия подключений: изолируйте сбои каждого клиента.
local data, err = client:receive("*l")
if err == "closed" then
client:close()
remove_from_watch(client)
endКорректное завершение работы
При завершении работы прекратите принимать подключения, закройте каждый активный клиентский сокет, а затем закройте сервер прослушивания, чтобы освободить порт.
Установка reuseaddr во время bind позволяет немедленно перезапустить сервер, не дожидаясь окончания периода TCP TIME_WAIT.
for _, c in ipairs(clients) do c:close() end
server:close()
print("server stopped")Быстрая проверка
Выберите последовательность вызовов, которая превращает новый главный сокет в работающий сокет прослушивания.
Итоги
Вы создали TCP-сервер: выполнили bind с reuseaddr, запустили прослушивание с ограничением длины очереди и организовали цикл на accept для обслуживания клиентов.
Вы рассмотрели простой итеративный цикл, а затем масштабировали его с помощью socket.select для неблокирующей параллельной обработки, добавив изоляцию ошибок и корректное завершение работы. Далее Вы перейдёте на уровень HTTP.
Часто задаваемые вопросы
Урок «Создание сервера» бесплатный?
Да — полный текст урока «Создание сервера» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Lua Academy, подпишись на CoddyKit PRO. Курс Lua Academy содержит 4 уроков всего.
Чему я научусь в уроке «Создание сервера»?
Принимайте входящие соединения. Ты практикуешь Lua Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Lua Academy?
Предыдущий опыт не требуется. Lua Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Создание сервера»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Lua Academy?
Да. Каждый урок Lua Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Основы TCP
- Создание клиента
- Создание сервера
- HTTP-запросы