0Pricing
Lua Academy · レッスン

クライアントを構築する

サーバーにデータを要求します。

「クライアントを構築する」はCoddyKit上の無料Lua Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLua Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Lua Academyコースには全4レッスンが含まれています。

クライアントのライフサイクル

TCPクライアントには、ソケットを作成し、サーバーに接続し、データを交換してからクローズするという明確なライフサイクルがあります。

LuaSocketでは各手順が1回のメソッド呼び出しに対応し、それぞれが失敗する可能性があります。適切に実装されたクライアントは、すべての戻り値を確認し、どのエラーパスでもソケットを確実にクリーンアップします。

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"パターンを使って読み取りを繰り返します。各呼び出しは、終端文字を除いた1行を返します。

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)

完全なエコークライアント

一連の流れは、接続し、1行を送信し、エコーされた行を読み取り、クローズするというものです。これは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()

切断への対処

サーバーはいつでも接続を切断できます。切断された相手に対するsendは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時間対応のAIチューター)、Lua Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Lua Academyコースには全4レッスンが含まれています。

「クライアントを構築する」で何を学びますか?

サーバーにデータを要求します。 ブラウザで直接実行するハンズオンコードでLua Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Lua Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのLua Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「クライアントを構築する」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このLua Academyレッスンでコードを書いて実行できますか?

はい。すべてのLua Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. TCPの基本
  2. クライアントを構築する
  3. サーバーを構築する
  4. HTTPリクエスト
← Lua Academyに戻る