Создание клиента
Запрашивайте данные у сервера.
«Создание клиента» — бесплатный урок Lua Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Lua Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Lua Academy содержит 4 уроков всего.
Жизненный цикл клиента
TCP-клиент проходит понятный жизненный цикл: создание сокета, подключение к серверу, обмен данными и закрытие соединения.
В LuaSocket каждый шаг выполняется одним вызовом метода, и каждый такой вызов может завершиться ошибкой. Хорошо написанный клиент проверяет каждое возвращаемое значение и закрывает свой сокет при любом сценарии ошибки.
local socket = require("socket")
local client = assert(socket.tcp())Безопасное подключение
Задайте тайм-аут подключения перед вызовом connect, чтобы недоступный узел не зависил надолго и не блокировал программу. Обычно достаточно нескольких секунд.
Если connect возвращает nil, запишите ошибку в журнал и прервите работу. Никогда не предполагайте, что рукопожатие прошло успешно.
client:settimeout(5)
local ok, err = client:connect("127.0.0.1", 8080)
if not ok then
client:close()
error("connect failed: " .. err)
endИспользование socket.connect
В распространённом случае socket.connect(host, port) объединяет создание и подключение. Он возвращает готовый объект клиента либо nil и ошибку.
Это краткая форма, но она не даёт установить тайм-аут до рукопожатия, поэтому в ненадёжных сетях предпочитайте явную форму.
local socket = require("socket")
local client, err = socket.connect("example.com", 13)
if not client then error(err) endОтправка запроса
После подключения запишите байты запроса с помощью send. Многие текстовые протоколы отделяют строки возвратом каретки + переводом строки (\r\n).
Поскольку TCP — это поток байтов, чётко завершайте каждое логическое сообщение, чтобы сервер знал, где оно заканчивается.
local msg = "PING\r\n"
local sent, err = client:send(msg)
if not sent then error("send failed: " .. err) endЧтение ответа построчно
Для протоколов, основанных на строках, читайте данные в цикле с шаблоном "*l". Каждый вызов возвращает одну строку без завершающего символа.
При получении nil проверьте ошибку: "closed" означает, что сервер разорвал соединение, а "timeout" — что данные не поступили вовремя.
client:settimeout(5)
local line, err = client:receive("*l")
if line then
print("server said:", line)
else
print("recv error:", err)
endЧтение ответа целиком
Протоколы запросов и ответов часто читают все данные до закрытия соединения сервером. Используйте "*a", чтобы получить всё тело ответа.
Если сначала частично закрыть сторону отправки с помощью shutdown("send"), сервер увидит конец входных данных и сможет завершить свой ответ.
client:send("GET DATA\r\n")
client:shutdown("send")
local body, err = client:receive("*a")
print(#(body or ""), "bytes received")Формирование сообщений фиксированной длины
Бинарные протоколы часто предваряют каждое сообщение его длиной. Сначала прочитайте заголовок с длиной, затем прочитайте ровно указанное количество байтов.
Передача числа в receive блокирует выполнение, пока не поступит указанное количество байтов или в сокете не возникнет ошибка, обеспечивая точное разделение сообщений в потоке байтов.
local header = client:receive(4)
local len = string.unpack(">I4", header)
local payload = client:receive(len)Полный эхо-клиент
Вот весь процесс: подключиться, отправить строку, прочитать строку, возвращённую сервером, и закрыть соединение. Это каноническая структура клиента LuaSocket.
Обратите внимание: для краткости каждый вызов, который может завершиться ошибкой, защищён с помощью assert, но настоящий клиент должен обрабатывать ошибки корректно.
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()Обработка отключений
Серверы могут разорвать соединения в любой момент. Отправка данных закрытому узлу может вернуть nil, "closed", а receive возвращает частичные данные вместе с ошибкой.
Считайте "closed" обычным конечным состоянием, а не сбоем. Логику переподключения следует размещать в оболочке повторных попыток вокруг клиента.
local data, err, partial = client:receive("*a")
if err == "closed" then
print("peer closed, got", #partial, "bytes")
endНеблокирующие клиенты
Задайте тайм-аут 0 для полностью неблокирующего клиента. В этом случае вызовы возвращаются немедленно и сообщают "timeout", когда дальнейшее продвижение невозможно.
Объедините это с socket.select, чтобы эффективно ожидать готовности множества сокетов без активного опроса в цикле.
client:settimeout(0)
local r = socket.select({client}, nil, 5)
if #r > 0 then print(client:receive("*l")) endРазрешение имён узлов
Если Вы подключаетесь по имени узла, LuaSocket разрешает его автоматически. Чтобы просмотреть или кэшировать результат разрешения, самостоятельно вызовите socket.dns.toip или socket.dns.getaddrinfo.
Однократное разрешение имени и подключение по IP позволяет избежать повторных запросов DNS в цикле частых переподключений.
local socket = require("socket")
local ip = assert(socket.dns.toip("example.com"))
local c = assert(socket.connect(ip, 80))Быстрая проверка
Выберите правильный способ прочитать всё, что сервер отправляет, до закрытия соединения.
Итоги
Вы создали TCP-клиент от начала до конца: подключались с тайм-аутом, формировали и отправляли запросы, читали построчные ответы, ответы заданной длины и целые потоки, а затем корректно закрывали соединение.
Вы также рассмотрели обработку отключений, неблокирующий режим с помощью select и кэширование DNS. Далее Вы напишете серверную часть, которая отвечает этим клиентам.
Часто задаваемые вопросы
Урок «Создание клиента» бесплатный?
Да — полный текст урока «Создание клиента» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Lua Academy, подпишись на CoddyKit PRO. Курс Lua Academy содержит 4 уроков всего.
Чему я научусь в уроке «Создание клиента»?
Запрашивайте данные у сервера. Ты практикуешь Lua Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Lua Academy?
Предыдущий опыт не требуется. Lua Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.
Сколько времени занимает урок «Создание клиента»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Lua Academy?
Да. Каждый урок Lua Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Основы TCP
- Создание клиента
- Создание сервера
- HTTP-запросы