สร้างเซิร์ฟเวอร์
ยอมรับการเชื่อมต่อขาเข้า
สร้างเซิร์ฟเวอร์ เป็นบทเรียน Lua Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 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())การ bind กับพอร์ต
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 ฟังก์ชันนี้จะคืนซ็อกเก็ตที่พร้อมอ่าน รวมถึงซ็อกเก็ตเซิร์ฟเวอร์ที่รอรับเมื่อมีไคลเอ็นต์ใหม่รออยู่
คุณจัดการ table ของไคลเอ็นต์ที่กำลังทำงานและประมวลผลเฉพาะไคลเอ็นต์ที่มีข้อมูล ทำให้ลูปเหตุการณ์แบบเธรดเดียวตอบสนองได้ดี
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" หรือบัฟเฟอร์บางส่วน ให้นำไคลเอ็นต์นั้นออกจาก table ที่ใช้เฝ้าดูและปิดซ็อกเก็ตของไคลเอ็นต์
อย่าปล่อยให้การเชื่อมต่อที่เสียหายเพียงรายการเดียวทำให้ลูปรอรับหยุดทำงาน ให้แยกการล้มเหลวของไคลเอ็นต์แต่ละรายออกจากกัน
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 รอรับการเชื่อมต่อด้วย backlog และวนลูปเรียกใช้ accept เพื่อให้บริการไคลเอ็นต์
คุณได้เห็นลูปแบบวนซ้ำอย่างง่าย จากนั้นจึงปรับขนาดด้วย socket.select เพื่อให้ทำงานพร้อมกันแบบไม่บล็อก รวมถึงการแยกการจัดการข้อผิดพลาดและการปิดระบบอย่างเรียบร้อย ต่อไปคุณจะเลื่อนขึ้นไปทำงานกับ HTTP
เรียนรู้ Lua ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 40
- บทเรียน
- 159
คำถามที่พบบ่อย
บทเรียน “สร้างเซิร์ฟเวอร์” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “สร้างเซิร์ฟเวอร์” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Lua Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Lua Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “สร้างเซิร์ฟเวอร์”
ยอมรับการเชื่อมต่อขาเข้า คุณปฏิบัติ Lua Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Lua Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Lua Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “สร้างเซิร์ฟเวอร์” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Lua Academy นี้ได้ไหม
ได้ บทเรียน Lua Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- พื้นฐาน TCP
- สร้างไคลเอนต์
- สร้างเซิร์ฟเวอร์
- คำขอ HTTP