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