0Pricing
Lua Academy · Урок

Создание клиента

Запрашивайте данные у сервера.

«Создание клиента» — бесплатный урок 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 — локальная установка не требуется.

Все уроки этого курса

  1. Основы TCP
  2. Создание клиента
  3. Создание сервера
  4. HTTP-запросы
← Назад к Lua Academy