0Pricing
Lua Academy · レッスン

サーバーを構築する

受信接続を受け付けます。

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

サーバーのライフサイクル

TCPサーバーはアドレスにバインドし、接続を待ち受け、その後、接続を受け付けてクライアントを処理するループを実行します。

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"を使用します。

別のプロセスがポートを使用している場合、バインドは"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)を使うと、バインドと待ち受けを1回の呼び出しで行い、準備済みのサーバーオブジェクトを返します。

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

1クライアントの処理

接続を受け付けた後は、返されたオブジェクトをクライアントソケットとまったく同じように扱います。receiveでリクエストを受け取り、sendで応答を送信します。

クライアントごとのソケットには専用のタイムアウトを設定し、1つの遅いクライアントがサーバー全体を停止させないようにしてください。

client:settimeout(10)
local line = client:receive("*l")
if line then client:send(line .. "\n") end
client:close()

接続受付ループ

典型的な逐次処理サーバーは、クライアントを受け付け、処理し、クローズするという流れを無限に繰り返します。これにより、一度に1クライアントを処理します。

シンプルで正しく動作しますが、遅いリクエストが後続のすべてのクライアントをブロックするため、同時に複数のクライアントを処理できません。

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

最小構成のエコーサーバー

ここまでの内容を組み合わせると、エコーサーバーはバインドして待ち受けを開始し、各クライアントの最初の行をそのまま返すループを実行します。

これは完全な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)を設定すると、acceptがブロックしなくなります。これをselectと組み合わせ、リスナーが実際に読み取り可能な場合だけacceptを呼び出します。

これは、数百の接続を多重化するスケーラブルな単一プロセスサーバーの基盤となります。

server:settimeout(0)
local ready = socket.select({server}, nil, 5)
if #ready > 0 then
  local c = server:accept()
end

クライアントエラーへの対処

クライアントは突然切断することがあります。receiveがnil, "closed"または部分的なバッファを返したら、そのクライアントを監視対象のテーブルから削除し、ソケットをクローズします。

1つの壊れた接続で接続受付ループ全体が停止しないように、各クライアントの失敗を分離してください。

local data, err = client:receive("*l")
if err == "closed" then
  client:close()
  remove_from_watch(client)
end

適切なシャットダウン

シャットダウン時には、新しい接続の受け付けを停止し、アクティブなクライアントソケットをすべてクローズしてから、ポートを解放するために待ち受け中のサーバーをクローズします。

バインド時にreuseaddrを設定すると、TCPのTIME_WAIT期間が終わるのを待たずにすぐ再起動できます。

for _, c in ipairs(clients) do c:close() end
server:close()
print("server stopped")

理解度チェック

新しいマスターソケットを動作するリスナーに変える呼び出しの順序を選んでください。

まとめ

reuseaddrを設定してバインドし、backlogを指定して待ち受けを開始し、acceptのループでクライアントを処理するTCPサーバーを作成しました。

シンプルな逐次処理ループを確認した後、socket.selectによるノンブロッキングの並行処理へ拡張し、エラーの分離と適切なシャットダウンも学びました。次は、HTTPへ進みます。

よくある質問

「サーバーを構築する」レッスンは無料ですか?

はい。「サーバーを構築する」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Lua Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Lua Academyコースには全4レッスンが含まれています。

「サーバーを構築する」で何を学びますか?

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

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

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

「サーバーを構築する」レッスンにはどのくらい時間がかかりますか?

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

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

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

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

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