สำหรับแอปพลิเคชันแบบเรียลไทม์หรือเกมเรียลไทม์โปรโตคอล HTTP มักจะไม่สามารถตอบสนองความต้องการของเราได้ ซ็อกเก็ตใช้งานได้จริงมากสำหรับเรา ด้านล่างนี้เป็นบันทึกย่อสำหรับการศึกษานี้ ส่วนใหญ่จะอธิบายถึงแง่มุมของประเภทข้อยกเว้นหลักการปฏิสัมพันธ์ซ็อกเก็ตเซิร์ฟเวอร์และมัลติเธรด
ประเภทข้อยกเว้น
ก่อนที่จะเข้าใจเนื้อหาของซ็อกเก็ตคุณต้องเข้าใจประเภทข้อยกเว้นบางประเภทที่เกี่ยวข้อง สี่ประเภทต่อไปนี้ทั้งหมดได้รับการสืบทอดมาจาก ioexception จำนวนมาก ioexception จะปรากฏขึ้นโดยตรงหลังจากนั้น
unkownhostexception: ชื่อโฮสต์หรือข้อผิดพลาด IP
ConnectException: เซิร์ฟเวอร์ปฏิเสธที่จะเชื่อมต่อเซิร์ฟเวอร์ไม่เริ่ม (จำนวนคิวเกินกว่าการเชื่อมต่อจะถูกปฏิเสธ)
SocketTimeOutException: การหมดเวลาเชื่อมต่อ
bindexception: วัตถุซ็อกเก็ตไม่สามารถผูกไว้กับที่อยู่ IP หรือพอร์ตที่กำหนด
กระบวนการโต้ตอบ
ฉันคิดว่าภาพต่อไปนี้ได้รับการอธิบายอย่างละเอียดและชัดเจน
ซ็อกเก็ต
ตัวสร้าง
ซ็อกเก็ต () ซ็อกเก็ต (ที่อยู่ inetaddress, พอร์ต int) โยน unknownhostexception, ioexceptionsocket (ที่อยู่ inetaddress, พอร์ต int, inetaddress localaddress, int localport) โยน ioexceptionsocket (สตริงโฮสต์, พอร์ต int)
ยกเว้นตัวแรกที่ไม่มีพารามิเตอร์ตัวสร้างอื่น ๆ จะพยายามสร้างการเชื่อมต่อกับเซิร์ฟเวอร์ หากล้มเหลวข้อผิดพลาดของ IOException จะถูกโยนลงไป หากประสบความสำเร็จวัตถุซ็อกเก็ตจะถูกส่งคืน
Inetaddress เป็นคลาสที่ใช้ในการบันทึกโฮสต์ GetHostByName (String MSG) แบบคงที่ของมันสามารถส่งคืนอินสแตนซ์และวิธีการคงที่ getLocalHost () ยังสามารถรับที่อยู่ IP ของโฮสต์ปัจจุบันและส่งคืนอินสแตนซ์ พารามิเตอร์ของซ็อกเก็ต (โฮสต์สตริง, พอร์ต int, inetaddress localaddress, int localport) ตัวสร้างคือ IP เป้าหมาย, พอร์ตเป้าหมาย, IP ในท้องถิ่นและพอร์ตท้องถิ่น
วิธีซ็อกเก็ต
getinetaddress (); ที่อยู่ IP ของเซิร์ฟเวอร์ระยะไกล
getPort (); พอร์ตของเซิร์ฟเวอร์ระยะไกล
getLocalAddress () ที่อยู่ IP ของไคลเอนต์ท้องถิ่น
GetLocalport () พอร์ตของไคลเอนต์ท้องถิ่น
getInputStream (); getInputStream ();
getOutstream (); รับกระแสเอาต์พุต
เป็นที่น่าสังเกตว่าในวิธีการเหล่านี้สิ่งที่สำคัญที่สุดคือ getInputStream () และ getOutputStream ()
สถานะซ็อกเก็ต
isclosed (); // การเชื่อมต่อปิดหรือไม่? หากปิดให้กลับมาจริง มิฉะนั้นให้ส่งคืน FALSE
isConnect (); // ส่งคืนจริงถ้าเชื่อมต่อ; มิฉะนั้นจะกลับเท็จ
Isbound (); // หากซ็อกเก็ตถูกผูกไว้กับพอร์ตท้องถิ่นให้ส่งคืนจริง มิฉะนั้นให้ส่งคืน FALSE
หากคุณต้องการยืนยันว่าสถานะของซ็อกเก็ตอยู่ในการเชื่อมต่อข้อความต่อไปนี้เป็นวิธีที่ดีในการตัดสิน
บูลีน isConnection = socket.isconnected () &&! socket.isclosed (); // ตัดสินว่ามีการเชื่อมต่อในขณะนี้
ซ็อกเก็ตกึ่งปิด
หลายครั้งที่เราไม่รู้ว่าต้องใช้เวลานานแค่ไหนในการจบการป้อนข้อมูลที่ได้รับ นี่คือวิธีการทั่วไปบางอย่าง:
เซิร์ฟเวอร์
ตัวสร้าง
Serversocket () พ่น IOExceptionServersocket (พอร์ต int) พ่น IOExceptionServersocket (พอร์ต int, int backlog) โยน iOexceptionServersocket (พอร์ต int, int backlog, inetaddress bindddr)
บันทึก:
1. พอร์ตที่จะฟังโดยพอร์ตเซิร์ฟเวอร์; ความยาวคิวของคำขอเชื่อมต่อไคลเอนต์ backlog; เซิร์ฟเวอร์ bindaddr ผูก IP
2. หากพอร์ตถูกครอบครองหรือไม่ได้รับอนุญาตให้ใช้พอร์ตบางอย่างข้อผิดพลาดของ bindexception จะถูกโยน ตัวอย่างเช่นพอร์ตจาก 1 ถึง 1023 กำหนดให้ผู้ดูแลระบบต้องมีผลผูกพัน
3. หากพอร์ตถูกตั้งค่าเป็น 0 ระบบจะกำหนดพอร์ตให้กับมันโดยอัตโนมัติ
4. bindaddr ใช้เพื่อผูกเซิร์ฟเวอร์ IP ทำไมจึงมีการตั้งค่าเช่นนี้? ตัวอย่างเช่นเครื่องบางเครื่องมีการ์ดเครือข่ายหลายใบ
5. เมื่อ Serversocket ถูกผูกไว้กับพอร์ตการฟังมันจะไม่สามารถเปลี่ยนแปลงได้ Serversocket () สามารถตั้งค่าพารามิเตอร์อื่น ๆ ก่อนที่จะเชื่อมโยงพอร์ต
ตัวอย่างเซิร์ฟเวอร์แบบเธรดเดี่ยว
บริการโมฆะสาธารณะ () {ในขณะที่ (จริง) {ซ็อกเก็ตซ็อกเก็ต = null; ลอง {socket = serversocket.accept (); // ใช้การเชื่อมต่อจากคิวการเชื่อมต่อถ้าไม่รอ System.out.println ("ที่อยู่:"+socket.getInetAddress ()+":" socket.getport ()); ... // รับและส่งข้อมูล} catch (ioexception e) {e.printstacktrace ();} ในที่สุด {ลอง {ถ้า (ซ็อกเก็ต! = null) socket.close (); // หลังจากการสื่อสารกับลูกค้าปิดซ็อกเก็ต} catch (ioexception e) {e.printstacktrace ();multithreaded serversocket
ไม่จำเป็นต้องพูดประโยชน์ของการทำมัลติเธรดเป็นแบบมัลติเธรดและสถานการณ์ส่วนใหญ่คือมัลติเธรด ไม่ว่าจะเป็นเกมหรือ IM แบบเรียลไทม์ของเราความต้องการแบบมัลติเธรดเป็นสิ่งจำเป็น พูดคุยเกี่ยวกับวิธีการใช้งานด้านล่าง:
วิธีการที่ใช้การเธรดมัลติ-มัลติเพอร์ม์อาจสืบทอดคลาสเธรดหรือใช้อินเทอร์เฟซที่เรียกใช้งานได้ แน่นอนว่าพูลเธรดสามารถใช้งานได้ แต่สาระสำคัญของการใช้งานจะคล้ายกัน
นี่คือตัวอย่าง:
รหัสต่อไปนี้เป็นเธรดหลักของเซิร์ฟเวอร์ กำหนดเธรดคนงานให้กับลูกค้าแต่ละราย:
บริการโมฆะสาธารณะ () {ในขณะที่ (จริง) {ซ็อกเก็ตซ็อกเก็ต = null; ลอง {socket = serversocket.accept (); // เธรดหลักได้รับเธรดการเชื่อมต่อไคลเอนต์ workThread = เธรดใหม่ (ตัวจัดการใหม่ (ซ็อกเก็ต)); // สร้างเธรด workthread.start (); // เริ่มเธรด} catch (Exception E) {E.printStackTrace (); -แน่นอนว่าการมุ่งเน้นที่นี่คือวิธีการใช้คลาส Handler Handler จำเป็นต้องใช้อินเทอร์เฟซ Runnable:
ตัวจัดการคลาสใช้งาน {ซ็อกเก็ตซ็อกเก็ตส่วนตัว; ตัวจัดการสาธารณะ (ซ็อกเก็ตซ็อกเก็ต) {this.socket = ซ็อกเก็ต; } โมฆะสาธารณะเรียกใช้ () {ลอง {system.out.println ("การเชื่อมต่อใหม่:"+socket.getInetAddress ()+":"+socket.getport ()); Thread.sleep (10,000); } catch (exception e) {e.printstacktrace ();} ในที่สุด {ลอง {system.out.println ("ปิดการเชื่อมต่อ:"+socket.getInetAddress ()+":"+socket.getport ()); ถ้า (ซ็อกเก็ต! = null) socket.close (); } catch (ioexception e) {e.printstacktrace (); - แน่นอนว่ามีวิธีอื่น ๆ ในการทำมัลติเธรดก่อนเช่นพูลเธรดหรือพูลเธรดที่สร้างขึ้นใน JVM ฉันจะไม่อธิบายที่นี่
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น