0Pricing
Lua Academy · บทเรียน

สร้างไคลเอนต์

ขอข้อมูลจากเซิร์ฟเวอร์

สร้างไคลเอนต์ เป็นบทเรียน 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. พื้นฐาน TCP
  2. สร้างไคลเอนต์
  3. สร้างเซิร์ฟเวอร์
  4. คำขอ HTTP
← กลับไปที่ Lua Academy