ภาษา: C++ พร้อมกาว Lua Logic
รหัสได้รับการทดสอบเพื่อคอมไพล์และรันบน Ubuntu x86, Ubuntu x86_64 และ Gentoo x86_64 เนื่องจากมีการใช้ LuaJIT เวอร์ชันที่เหมาะสม การปรับเปลี่ยน libjansson เพื่อลบการจัดรูปแบบบังคับของการลอยตัวด้วย .0 หลังจากที่ตัวเลขทั้งหมดเสร็จสิ้นเพื่อรองรับ "จำนวนเต็ม" อย่างเหมาะสม และยังคงมีการแปลงอัตโนมัติจาก Lua ซึ่งรองรับเฉพาะเลขคู่เท่านั้น
นอกจากนี้ยังคอมไพล์บน Ubuntu 12.04 LTS x86_64 เนื่องจาก libjansson และ google-glog ถูกสร้างขึ้นด้วยตนเอง
ลัวจิต
ลิเบฟ
evhttpclient
google-glog
google-perftools (tcmalloc) - ตัวเลือกที่มีการแก้ไขซอร์สรองและ makefile
ลิบยานสัน
จ้าง
libicu - ดูตัวจัดการแพ็คเกจในเครื่อง
curl - ดูตัวจัดการแพ็คเกจในเครื่อง
เพิ่ม - เป็นทางเลือกหากคุณแทนที่พอยน์เตอร์ที่รบกวนด้วยสิ่งของคุณเอง
อาจจำเป็นต้องมีการปรับเปลี่ยน src/Makefile เพื่อให้สะท้อนถึงโฟลเดอร์การติดตั้งของคุณ ยินดีรับระบบการสร้างที่แข็งแกร่งกว่านี้ แต่ไม่จำเป็นในขณะที่เขียนโครงการ (ซีเมค?)
ฉัน (@zwagoth) เรียนรู้บางอย่างที่นี่: แสดงความคิดเห็นเสมอในขณะที่เขียน เพื่อชดเชยสิ่งนี้ ฉันจะ บันทึกโครงสร้างพื้นฐานของโปรแกรมเพื่อช่วยในการทำความเข้าใจ
ขออภัยสำหรับความยุ่งเหยิงของ codebase นี่เป็นหนึ่งในโปรเจ็กต์ C++ แรกๆ ของฉันในทุกขนาดและความซับซ้อน
ประกอบด้วยตรรกะหลักเกือบทั้งหมดสำหรับการจัดการข้อความของข้อความโปรโตคอล ข้อความ RTB และการเรียกกลับเหตุการณ์พื้นฐานต่างๆ เช่น การเชื่อมต่อและการตัดการเชื่อมต่อ
ไฟล์ประกอบด้วยตารางของฟังก์ชันที่ไม่ระบุชื่อซึ่งตั้งชื่อตามเหตุการณ์ที่ฟังก์ชันจัดการ ไฟล์นี้ไม่ควรเก็บสถานะใดๆ และถือเป็นพื้นที่จัดเก็บลอจิกเท่านั้น การออกแบบพื้นฐานของไฟล์นี้คือการอนุญาตให้ใช้ตรรกะกาวโดยไม่ต้องบังคับให้ Lua ทำการยกของหนักและลดปริมาณข้อมูลที่ถ่ายโอนเข้าและออกจาก Lua โดยเสียค่าใช้จ่ายในการเรียกใช้ฟังก์ชันเพิ่มเติมใน C ++
มีสี่ตารางที่แทรกเข้าไปในเนมสเปซไฟล์โกลบอลพร้อมชื่อสั้น ๆ เพื่อความสะดวกในการพิมพ์:
u
: ฟังก์ชั่นการเชื่อมต่อ/ตัวละคร(ผู้ใช้)
s
: ฟังก์ชันเซิร์ฟเวอร์/สถานะสากล
c
: ฟังก์ชั่นสถานะของช่อง
const
: รหัสข้อผิดพลาดและค่าคงที่
ฟังก์ชันการเรียกกลับโปรโตคอลยอมรับพารามิเตอร์สองตัว การเชื่อมต่อที่เชื่อมโยงกับคำสั่ง และสำเนาตารางของอาร์กิวเมนต์ json ที่ให้ไว้
การเชื่อมต่อเป็นตัวเลขทึบแสง และไม่ควรแก้ไขใดๆ การเปลี่ยนค่าของการเชื่อมต่อไม่ปลอดภัย คุณได้รับคำเตือน
ไฟล์ lua ของตัวแปรคอนฟิกูเรชันที่ใช้ระหว่างการเริ่มต้นและการทำงานของ chat daemon
เซิร์ฟเวอร์นโยบายแฟลชที่เรียบง่าย หากคุณต้องการรองรับ Flash นี่คือสิ่งที่คุณดำเนินการ ปรับแต่งนโยบายอินไลน์ตามความต้องการของคุณ
จุดเข้าโปรแกรม จัดการกับการเริ่มต้นเธรดพื้นหลังและขด
ทำหลายสิ่งหลายอย่างเกินไป การไหลของโค้ดเริ่มต้นที่ Server::run()
ขั้นตอนการเชื่อมต่อมีดังนี้:
listenCallback handshakeCallback connectionWriteCallback connectionReadCallback connectionwriteCallback
listenCallback
ตั้งค่าตามตัวจัดการเหตุการณ์การเชื่อมต่อและส่งผ่านไปยัง...
handshakeCallback
ซึ่งจัดการการอ่านการจับมือ websocket
connectionWriteCallback
จัดการเมื่อการเชื่อมต่อพร้อมที่จะเขียนและเปิดใช้งานเมื่อรายการอยู่ในคิวที่จะเขียนไปยังการเชื่อมต่อ จัดการบัฟเฟอร์
connectionReadCallback
จัดการเหตุการณ์การอ่านทั้งหมดเมื่อเฟสการจับมือสิ้นสุดลง การแยกวิเคราะห์โปรโตคอลทั้งหมดเกิดขึ้นที่นี่ และคำสั่งต่างๆ จะถูกส่งและเรียกใช้จากภายในฟังก์ชันนี้
pingCallback
จัดการการส่งเหตุการณ์ ping ไปยังไคลเอนต์ หากโปรโตคอลมีการเปลี่ยนแปลง นี่ควรเป็นหนึ่งในสิ่งแรกๆ ที่ต้องทำ
connectionTimerCallback
เริ่มทำงานเป็นระยะและตรวจสอบว่าการเชื่อมต่อเสียหรือไม่และทำความสะอาด
runLuaEvent
เป็นเวทย์มนตร์ของนิวท์ นอกจากนี้เวทย์มนตร์ยังเกิดขึ้นสำหรับแต่ละคำสั่งอีกด้วย นี่คือที่ที่แต่ละคำสั่งเปลี่ยนเป็นรหัส Lua จากรหัส C ++ จัดการสถานะ Lua ทั้งหมดและการเรียกกลับเพื่อให้แน่ใจว่า Lua จะไม่ติดอยู่ในลูปที่ไม่มีที่สิ้นสุด จัดการข้อผิดพลาดในการพิมพ์จากภายใน Lua
ไฟล์นี้เก็บข้อมูลสถานะทั้งหมดที่เกี่ยวข้องกับช่อง การเชื่อมต่อ การแบน และการกลั่นกรอง
การเชื่อมต่อจะถูกแบ่งระหว่างการระบุและไม่ปรากฏหลักฐาน เนื่องจากไม่ทราบชื่ออักขระจนกว่าเซิร์ฟเวอร์เข้าสู่ระบบจะตรวจสอบว่ามีอยู่จริง และป้องกันไม่ให้มีอักขระจำนวนมากที่สามารถค้นหาด้วยชื่อได้
จัดการการบันทึกและการกู้คืนสถานะไปยังดิสก์
ทำงานเป็นเธรดพื้นหลังที่ประมวลผลคำขอเข้าสู่ระบบและการตอบกลับและส่งกลับไปยังเธรดหลัก
ระบบการเข้าสู่ระบบแบบอนุกรม ใช้คิวการเข้าสู่ระบบทั่วโลก สิ่งนี้สามารถปรับปรุงได้ไม่น้อย
การแปลงเป็น curl_multi คงจะดี แต่เกี่ยวข้องกับการโต้ตอบที่สนุกสนานกับ libev หรือการสำรวจแบบ blind polling มากมาย คิวต้องถูกล็อคก่อนจึงจะเข้าถึงได้ เนื่องจากการเธรด
คลาสแชนเนลพื้นฐาน จะรักษาข้อมูลสถานะเกี่ยวกับแชนเนลตลอดอายุการใช้งาน การดำเนินการระดับต่ำทั้งหมดที่เกี่ยวข้องกับช่องเกิดขึ้นในไฟล์นี้ผ่าน hooks ใน Lua โดยปกติแล้วจะรวมอยู่ในพอยน์เตอร์ที่รบกวนเพื่อจัดการอายุการใช้งานของอินสแตนซ์
นี่คือจุดที่การทำให้เป็นอนุกรมและดีซีเรียลไลซ์ของช่องจาก json เกิดขึ้น
จัดการการเชื่อมต่อเครือข่ายทั้งหมดและดีบักสถานะ Lua
รักษารายการหงิกงอ สถานะ ข้อความสถานะ และเพศ
รักษาละเว้นและรายชื่อเพื่อน
จัดการต่อคันเร่งเชื่อมต่อ
นี่คือจุดที่การบัฟเฟอร์ข้อมูลเอาต์พุตเกิดขึ้น
โดยทั่วไปแล้วจะมีการส่งต่อโดยใช้พอยน์เตอร์ที่รบกวนเพื่อจัดการอายุการใช้งานของอินสแตนซ์
รักษารายการภายในของช่องที่เข้าร่วม สิ่งนี้จะต้องซิงค์กับรายชื่อผู้ใช้ช่องจริง
ไฟล์นี้สงวนไว้สำหรับฟังก์ชันบางอย่างที่ต้องใช้ความเร็วจริงมากกว่าการปรับแต่งได้ จัดการคำสั่งเข้าสู่ระบบ ( IDN
) จัดการคำสั่ง debug ( ZZZ
) จัดการคำสั่งการค้นหา ( FKS
)
คำสั่ง wrapper Lua ทั้งหมดที่อยู่ในหมวดหมู่ s
ในไฟล์ Lua
คำสั่ง wrapper Lua ทั้งหมดที่อยู่ในหมวดหมู่ u
ในไฟล์ Lua
คำสั่ง wrapper Lua ทั้งหมดที่อยู่ในหมวดหมู่ c
ในไฟล์ Lua
ค่า wrapper Lua ทั้งหมดที่อยู่ในหมวดหมู่ const
ในไฟล์ Lua
ข้อความแสดงข้อผิดพลาดและคำจำกัดความ
ใช้มาโครที่กำหนดไว้สำหรับข้อผิดพลาดและการตรวจสอบประเภท! นี่เป็นวิธีเดียวที่จะป้องกันการหยุดทำงานหากประเภทที่ไม่ถูกต้องถูกส่งผ่านเป็นข้อมูลที่มีน้ำหนักเบาไปยังฟังก์ชันโดยไม่คาดคิด
ตรวจสอบให้แน่ใจว่ากอง Lua ของคุณมียอดคงเหลือ ฉันพยายามอย่างหนักเพื่อให้แน่ใจว่านี่เป็นเรื่องจริง แต่ข้อผิดพลาดเกิดขึ้นได้ง่าย
หลีกเลี่ยงการคืนตารางเป็นโค้ด Lua เนื่องจากมีราคาแพงในการสร้างและมักจะมีกรอบเวลาการใช้งานสั้น ใช้วิจารณญาณที่ดีที่สุดเพื่อสร้างสมดุลระหว่างต้นทุนของการเรียกใช้ฟังก์ชันและต้นทุนของการสร้างตาราง
หลีกเลี่ยงการส่งสตริงไปยัง Lua โดยไม่จำเป็น อาจมีค่าใช้จ่ายสูงเนื่องจากสำเนาหน่วยความจำ
การละเมิดที่ lua ยอมรับค่าส่งคืนหลายค่าเป็นคุณลักษณะดั้งเดิม ดูบันทึกสองฉบับด้านบน
จัดการเธรด Redis แบบกดเท่านั้น เป็น wrapper ขนาดเล็กรอบๆ คำสั่ง Redis และค่าที่ส่งคืน
ใช้คิวอินพุตเพื่อรับคำสั่ง คำสั่งจะดำเนินการเป็นระยะๆ และไม่มีการรับประกันความน่าเชื่อถือ สามารถปิดใช้งานได้ และละเว้นอินพุตเมื่อปิดใช้งาน
gdb ทำงานได้ดีสำหรับการดีบักแอปพลิเคชันนี้ การปิดใช้งาน tcmalloc และส่วน JIT ของ LuaJIT น่าจะช่วยในการแก้ไขจุดบกพร่องได้อย่างมาก (tcmalloc สามารถซ่อนความเสียหายของฮีปเล็กน้อยได้)
เครื่องมือสร้างโปรไฟล์หน่วยความจำใน tcmalloc นั้นค่อนข้างดี โปรดดูเอกสารประกอบ tcmalloc สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการใช้งาน