คู่มือเกมแลค › L8 ซ็อกเก็ตและโปรโตคอล
keepalive ค่าเริ่มต้น 2 ชั่วโมง TCP keepalive defaults
ID สาเหตุ sk-keepalive · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
เปิดการ์ดในฉบับหลักที่มีภาพและการทดลอง →
ถ้าอีกฝั่งหายไปโดยไม่ส่งสัญญาณปิด TCP จะรู้ตัวหลังผ่านไปนานมาก keepalive (ฟีเจอร์ของ TCP ที่ตรวจว่าการเชื่อมต่อที่ idle ยังอยู่หรือไม่) ปิดไว้เป็นค่าเริ่มต้น และต่อให้เปิด ก็ต้อง idle ครบ 2 ชั่วโมงก่อนจึงเริ่มตรวจ
ทำไม ไคลเอนต์หายไปโดยไม่ส่งสัญญาณปิด เพราะเครื่องดับหรือเน็ตขาด → ผลคือ เซิร์ฟเวอร์ถือว่าการเชื่อมต่อยังอยู่ (keepalive ค่าเริ่มต้น 7,200 วินาที ถ้ามีข้อมูลที่กำลังส่งอยู่ จะใช้ประมาณ 15 นาทีกว่าจะเลิกส่งซ้ำ) → บนหน้าจอ เหลือตัวผีของตัวละครอยู่ในเกม และพอเชื่อมต่อใหม่ก็เจอข้อผิดพลาด “ล็อกอินอยู่แล้ว”
- อาการ
- เข้าเกมไม่ได้/โหลดไม่จบ, มองไม่เห็น/ตัวผี
- ปัจจัย
- แพ็กเก็ตหาย
- ใครเจอ
- เราคนเดียว
- เกิดเมื่อไร
- หลังอยู่เฉย ๆ สักพัก, หลังล็อกอิน/หลังปิดปรับปรุง
- ผู้รับผิดชอบ
- ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ พัฒนาไคลเอนต์ (ทีมพัฒนาเกม), อินฟราเซิร์ฟเวอร์ (ทีมอินฟรา)
- งานฝั่งทีมพัฒนาเกม
- เซิร์ฟเวอร์: ตอบ heartbeat และถ้าไม่ได้รับนานเกินกำหนดให้ปิดการเชื่อมต่อเองก่อน (ปรับ TCP_KEEPIDLE และ TCP_USER_TIMEOUT), เมื่อเชื่อมต่อใหม่ให้ใช้ session token แทนที่เซสชันเดิมแล้วเล่นต่อ ไคลเอนต์: ส่ง heartbeat ระดับเกมทุกไม่กี่วินาทีถึงหลายสิบวินาที (ไม่เกินครึ่งหนึ่งของ idle timeout ที่สั้นที่สุด), เชื่อมต่อใหม่อัตโนมัติเมื่อหลุด
- งานฝั่งทีมอินฟรา
- ลดค่าเริ่มต้นของเคอร์เนล (tcp_keepalive_time เป็นต้น) สำหรับซ็อกเก็ตที่โค้ดไม่ได้กำหนดค่าเอง (มีผลเฉพาะซ็อกเก็ตที่เปิด SO_KEEPALIVE)
- ตัวเลขที่ควรรู้
- ค่าเริ่มต้นของ Linux จะเริ่มตรวจเมื่อ idle ครบ 7,200 วินาที แล้วส่ง probe 9 ครั้งห่างกันครั้งละ 75 วินาที ถ้าไม่มีการตอบกลับเลยจะตัดการเชื่อมต่อ รวมแล้วประมาณ 2 ชั่วโมง 11 นาที ค่าเริ่มต้นของ Windows ก็ต้อง idle 2 ชั่วโมงก่อนจึงเริ่มตรวจเช่นกัน
- บนกราฟ
- สูงเฉพาะบางกลุ่ม · เวลาที่ผ่านไปนับจากรับข้อมูลครั้งล่าสุดของแต่ละการเชื่อมต่อ
- จุดที่ต้องดู
- lastrcv (ms ที่ผ่านไปนับจากรับข้อมูลครั้งล่าสุด) และตัวจับเวลา keepalive (timer:(keepalive,…)) ของแต่ละการเชื่อมต่อจาก ss -tnoi เทียบกับบันทึกการปฏิเสธ “ล็อกอินอยู่แล้ว” ของเซิร์ฟเวอร์เกม
- สัญญาณว่าใช่
- ยังมีการเชื่อมต่อ ESTABLISHED ที่ lastrcv นานหลายนาทีถึงหลายชั่วโมง และการเชื่อมต่อใหม่ของบัญชีนั้นถูกปฏิเสธด้วย “ล็อกอินอยู่แล้ว”
- สัญญาณว่าไม่ใช่
- ไม่มีการเชื่อมต่อที่เงียบไปนาน แต่ยังขึ้น “ล็อกอินอยู่แล้ว”: น่าจะเป็นโค้ดเก็บกวาดเซสชันของเซิร์ฟเวอร์เกม
- วิธีตรวจ
- ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง
- tcp(7) — Linux manual page Linux man-pages
หลัง idle 7,200 วินาที ส่ง probe 9 ครั้งห่างกัน 75 วินาที (เพิ่มอีกประมาณ 11 นาที), มีผลเฉพาะซ็อกเก็ตที่เปิด SO_KEEPALIVE, TCP_KEEPIDLE และ TCP_USER_TIMEOUT - RFC 9293: Transmission Control Protocol (TCP) IETF
keepalive ต้องปิดเป็นค่าเริ่มต้น และช่วง idle เริ่มต้นต้องไม่ต่ำกว่า 2 ชั่วโมง - SO_KEEPALIVE socket option Microsoft
ไทม์เอาต์เริ่มต้นของ TCP keepalive บน Windows คือ 2 ชั่วโมง - ss(8) — Linux manual page iproute2
lastrcv (ms ที่ผ่านไปนับจากรับข้อมูลครั้งล่าสุด) ใน -i, timer:(keepalive,…) ใน -o
สาเหตุที่ควรดูประกอบ
ชั้นเดียวกัน: L8 ซ็อกเก็ตและโปรโตคอล
สาเหตุจากชั้นอื่นที่ทำให้เกิดอาการเดียวกัน (เข้าเกมไม่ได้/โหลดไม่จบ)
ดูการ์ดในฉบับหลักที่มีภาพและการทดลอง