โซลูชันสำหรับการค้นพบ LAN ที่มีน้ำหนักเบาหรือไม่


9

ฉันสร้างห้องสมุดสำหรับการเขียนโปรแกรมข้ามแพลตฟอร์มล้วนๆ เกมของฉันทำงานได้ดีใน Android, PC, Linux, Mac และอื่น ๆ

ความสามารถในการเชื่อมต่อเครือข่ายนั้นมาจากไลบรารีของ ENET ดังนั้นการสื่อสารทั้งหมดระหว่างแอพของฉันไม่เข้ากันได้กับ TCP หรือ UDP แต่เฉพาะในโปรโตคอลที่กำหนดเองเท่านั้น

ฉันไม่คิดว่าเป็นไปได้ที่จะทำสิ่งที่ฉันต้องการด้วย ENET นั่นเป็นเหตุผลที่ฉันขอความช่วยเหลือที่นี่!

ให้บอกว่าฉันมีเกมเดียวกันที่ทำงานในโทรศัพท์ Android แล็ปท็อปและพีซีของฉัน พวกเขาทั้งหมดอยู่ในเครือข่าย wifi เดียวกันและดังนั้นใน LAN ไม่ว่าจะเป็นฮอตสปอต Wifi (?) หรือเราเตอร์ในครัวเรือน

ฉันต้องการเพื่อนทั้งสามคนนี้เพื่อค้นหาอีกสองคนในเครือข่าย นี่เป็นเพียงการหาไอพีของแอพที่มีชีวิตในเครือข่าย LAN เพื่อให้สามารถโฮสต์เกมแบบผู้เล่นหลายคนระหว่างพวกเขาได้

ฉันสามารถคิดถึงวิธีที่มีประสิทธิภาพเพียงวิธีเดียวในการทำเช่นนี้การออกอากาศ UDP รอการตอบกลับ แต่ถ้านั่นเป็นวิธีแก้ปัญหาฉันต้องมีบางสิ่งบางอย่างเล็ก ๆ

วิธีอื่นอาจลองเชื่อมต่อกับ IP ทั้งหมดในช่วงย่อยที่อยู่ LAN แต่ฉันไม่คิดว่าระบบปฏิบัติการจะอยู่กับฉันในรายการนี้: p


2
ฉันคิดว่าการออกอากาศ UDP สองสามครั้งเป็นวิธีที่จะไปและฉันไม่เข้าใจการคัดค้านของคุณหรือว่า ENET ไม่สนับสนุนการออกอากาศ
Roy T.

ว่ามันไม่ได้ก็สามารถถ่ายทอดเฉพาะกับเพื่อนที่รู้จักกันแล้ว ..
กริมชอว์

stackoverflow.com/questions/683624/…สิ่งนี้มีอิทธิพลต่อคำตอบหรือไม่?
Grimshaw

คำตอบ:


5

ตามที่หลาย ๆ คนบอกว่าวิธีการแก้ปัญหาคือใช้การออกอากาศ UDPแต่มีรายละเอียดการใช้งานมากมายที่เกี่ยวข้อง ฉันเพิ่งพบปัญหาเดียวกันและหลังจากหาวิธีแก้ปัญหาฉันได้โพสต์บล็อกและโครงการตัวอย่างในรูปแบบของเซิร์ฟเวอร์แชท / ไคลเอ็นต์ LAN ฉันจะสรุปที่นี่ แต่คุณควรตรวจสอบรายละเอียดเพิ่มเติมและรหัสจริง

นี่คือวิธีการทำงานตามคำอธิบายโดย Lee Salzman ผู้สร้าง ENet:

  • เซิร์ฟเวอร์เกมของคุณทำงานบนซ็อกเก็ตเดียวเป็นโฮสต์ของ ENet
  • เซิร์ฟเวอร์จะผูกเข้ากับพอร์ต "Listen" ที่รู้จักกันเป็นซ็อกเก็ต UDP ปกติ (เช่นไม่ใช่โฮสต์ ENet)
  • ไคลเอนต์ส่งข้อความออกอากาศ UDP (เช่น IP 255.255.255.255) ไปยังพอร์ตฟังนั้นและรอการตอบกลับ
  • เซิร์ฟเวอร์ทั้งหมดใน LAN จะได้รับข้อความ "สแกน" และตอบกลับ เป็นการดีที่คุณสามารถตอบสนองกับพอร์ตที่เซิร์ฟเวอร์เกม (โฮสต์ ENet) กำลังทำงานอยู่; ด้วยวิธีนี้คุณไม่จำเป็นต้องให้เซิร์ฟเวอร์เกมของคุณทำงานบนพอร์ตคงที่)
  • หลังจากที่ลูกค้าได้รับการตอบสนองบางอย่างมันจะรู้ว่ามีเซิร์ฟเวอร์ใดบ้าง จากนั้นคุณสามารถเลือกหนึ่งในนั้นเพื่อเชื่อมต่อเป็นเพียร์ ENet ปกติ ณ จุดนี้ลูกค้าไม่จำเป็นต้องใช้ซ็อกเก็ต "สแกนเนอร์" UDP อีกต่อไป

ข่าวดีก็คือว่า ENet มีฟังก์ชั่น wrapper สำหรับการใช้ซ็อกเก็ตดังนั้นคุณสามารถทำทุกอย่างใน ENet ข่าวร้ายคือเสื้อคลุมบางมาก คุณจะต้องรู้เกี่ยวกับการเขียนโปรแกรมซ็อกเก็ตเช่นสิ่งที่select()ไม่ นี่คือเหตุผลที่ฉันขอแนะนำให้คุณดูที่โพสต์บล็อกและตัวอย่างโครงการเพื่อให้คุณสามารถคัดลอก / วางรหัสและประหยัดเวลาได้มาก

ต่อไปนี้เป็นหมายเหตุและข้อผิดพลาดบางประการที่คุณควรเลือกเพื่อนำไปใช้งานของคุณเอง:

  • ตัวฟัง / สแกนเนอร์จะต้องเป็น UDP ดังนั้นคุณต้องสร้างโดยใช้enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM)(หรือSOCK_DGRAMสำหรับการเขียนโปรแกรมซ็อกเก็ตเก่าแบบธรรมดา)
  • สำหรับเซิร์ฟเวอร์ "listener" อนุญาตให้ใช้ที่อยู่พอร์ตอีกครั้งโดยใช้enet_socket_set_option(socket, ENET_SOCKOPT_REUSEADDR, 1)(หรือSO_REUSEADDR) เพื่อให้เซิร์ฟเวอร์หลายเครื่องสามารถทำงานบน IP เดียวกัน
  • สำหรับลูกค้า "สแกนเนอร์" คุณต้องเปิดใช้งานการออกอากาศในซ็อกเก็ต UDP โดยใช้enet_socket_set_option(scanner, ENET_SOCKOPT_BROADCAST, 1)(หรือSO_BROADCAST) มิฉะนั้นคุณจะไม่สามารถส่งไปยังที่อยู่การออกอากาศ นี่เป็นคุณลักษณะด้านความปลอดภัยเท่านั้นเพื่อให้ยากขึ้นในการทำให้เครือข่ายเสียหายโดยไม่ได้ตั้งใจ

น่าเสียดายที่นี่ไม่ใช่โซลูชันที่ "จริงจัง" อย่างแน่นอน ตัวอย่างโครงการนาฬิกาเข้าที่ LOC สักสองสามร้อยทั้งหมด มันคงจะดีถ้าสิ่งนี้ถูกบรรจุไว้ในยูทิลิตี้ไลบรารี่สำหรับ ENet แต่ฉันพบว่าสำหรับเซิร์ฟเวอร์เกมคุณมักจะต้องการส่งข้อมูลเฉพาะเกมเพิ่มเติมด้วยการตอบกลับจากเซิร์ฟเวอร์เพื่อให้มีประโยชน์เช่น:

  • ประเภทเกม (เช่น "co-op", "Deathmatch")
  • "แผนที่", "ระดับ" หรือ "แคมเปญ" เซิร์ฟเวอร์กำลังทำงาน
  • จำนวนผู้เล่นและผู้เล่นสูงสุดสำหรับเซิร์ฟเวอร์
  • ข้อมูลเฉพาะของเกมอื่น ๆ ที่จะมีผลต่อการตัดสินใจของลูกค้าในการเชื่อมต่อหรือไม่ คิดถึง "เบราว์เซอร์เซิร์ฟเวอร์" ในเกมและเรียงลำดับข้อมูลที่แสดง

นี่คือสิ่งที่ฉันคิด การออกอากาศเป็นวิธีที่จะไป
Lolums

3

เมื่อคุณไม่ต้องการออกจากห้องสมุดคุณสามารถใช้กำลังดุร้ายและพยายามเชื่อมต่อกับที่อยู่ที่เป็นไปได้แต่ละอัน เครือข่ายภายในบ้านส่วนใหญ่เป็นเครือข่าย Class-C (/ 24) โดยที่ 24 บิตแรกของที่อยู่ IP เหมือนกันและ 8 บิตสุดท้ายแตกต่างกัน ดังนั้นคุณมีที่อยู่ IP ที่เป็นไปได้ 255 รายการเท่านั้น

แต่ถึงกระนั้นการออกอากาศ UDP จะเป็นทางเลือกที่สะอาดกว่า เพียงส่งแพ็กเก็ต UDP ไปที่ 255.255.255.255 และไคลเอนต์ทั้งหมดที่อยู่หลังเราเตอร์เดียวกันจะได้รับ จากนั้นพวกเขาสามารถส่งการตอบกลับไปยัง IP ต้นทางและพอร์ตต้นทางของแพ็คเก็ตเพื่อแจ้งผู้ส่งว่ามีอยู่


2
โปรดกรุณาโปรดกรุณา โปรดไม่แรงเดรัจฉาน
เทรเวอร์พาวเวลล์

@TrevorPowell ... เพราะ ...
ฟิลิปป์

2
เพราะมันเป็นทางออกที่ผิด มันจะไม่ทำงานในมหาวิทยาลัย (ซึ่งไม่ได้ใช้เครือข่าย class-c) หรือที่ธุรกิจ (ซึ่งโดยปกติจะไม่ใช้เครือข่าย class-c) และพนักงานไอทีที่จะไม่ชอบภาระที่เกิดจากการมีผู้เล่นทุกคนทำ กำลังพยายามส่งข้อความไปยังทุกที่อยู่ IP ในเครือข่ายของพวกเขาทุกครั้งที่พวกเขาคลิกปุ่ม 'รีเฟรช' มันเป็นเพียงการแก้ปัญหาที่ไม่ดีในการแก้ไขปัญหา คำถามของการหาเพียร์ที่มีศักยภาพโดยไม่มีเซิร์ฟเวอร์ mathmaking เป็นสิ่งที่แม่นยำสำหรับการออกอากาศ ใช้การออกอากาศ มันจะดีกว่าในทุก ๆ ด้าน :)
Trevor Powell

1

คุณอาจจะมีลักษณะที่DNS-SD / ZeroConf / Avahi / Bonjour / mDNS มันเป็นสิ่งที่ Apple ใช้ในการแบ่งปันเครื่องพิมพ์โฟลเดอร์ iTunes และอื่น ๆ แต่ถูกนำไปใช้ที่อื่น Avahi เป็นรุ่น opensource ที่ลีนุกซ์ใช้ (ไม่แน่ใจว่าเป็นลินุกซ์เท่านั้น), ไม่แน่ใจว่าอุปกรณ์พกพาเป็นอย่างไร (แม้ว่าจะมีการติดตั้งใช้งานสำหรับแพลตฟอร์มส่วนใหญ่)

ถ้าพูดอย่างนั้นมันคงง่ายกว่าถ้าจะทำการถ่ายทอด UDP

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.