1. การวิเคราะห์เปิด
เริ่มตั้งแต่วันนี้มาเรียนรู้รายละเอียดในโมดูลเฉพาะ บทความนี้เป็นบทความที่สามในชุดนี้ สองบทความแรกส่วนใหญ่ขึ้นอยู่กับทฤษฎี ฉันเชื่อว่าในการศึกษาบทความสองบทความแรก
ฉันยังมีความเข้าใจพื้นฐานเกี่ยวกับ nodejs ก็โอเค! - - การโจมตีในขณะที่เหล็กร้อนมาขอให้พก nodejs ต่อไป เอาล่ะโดยไม่พูดเรื่องไร้สาระมากไปที่หัวข้อ "โมดูลสุทธิ" ของวันนี้โดยตรง ดังนั้น "ตาข่าย" ควรเข้าใจได้อย่างไร?
มันมีไว้เพื่ออะไร? (โมดูล Net สามารถใช้ในการสร้างเซิร์ฟเวอร์ซ็อกเก็ตหรือซ็อกเก็ตไคลเอนต์สองโมดูลพื้นฐานที่สุดสำหรับการสื่อสารข้อมูล NODEJS คือ NET และ HTTP อดีตคือการห่อหุ้มที่ใช้ TCP ในขณะที่หลังเป็นชั้น TCP แต่ได้ทำการห่อหุ้มข้อมูลจำนวนมาก
ที่นี่เราอ้างถึงซอร์สโค้ดใน nodejs "http.js":
ไม่ยากที่จะเห็นจากรูปที่ Httpserver สืบทอดคลาสสุทธิมีความสามารถในการสื่อสารที่เกี่ยวข้องและได้ทำการห่อหุ้มข้อมูลมากขึ้นซึ่งเราถือว่าเป็นเลเยอร์การเป็นตัวแทนขั้นสูง
ความรู้เพิ่มเติม (ต่อไปนี้เป็นซอร์สโค้ดของ "สืบทอด"):
การคัดลอกรหัสมีดังนี้:
exports.inherits = function (ctor, superctor) {
ctor.super_ = superctor;
ctor.prototype = object.create (superctor.prototype, {
ตัวสร้าง: {
ค่า: ctor,
enumerable: FALSE,
เขียนได้: จริง
สามารถกำหนดค่าได้: จริง
-
-
-
ฟังก์ชั่นคือการตระหนักถึงการสืบทอดและนำกลับมาใช้ใหม่
ฉันเพิ่งให้ภาพรวมสั้น ๆ ซึ่งมีแนวคิดที่ใช้กันทั่วไป นี่คือการแนะนำสั้น ๆ เกี่ยวกับแนวคิดที่เป็นที่นิยม:
(1) TCP/IP ---------- โปรโตคอล TPC/IP เป็นโปรโตคอลการขนส่งเลเยอร์ซึ่งส่วนใหญ่จะแก้ปัญหาการส่งข้อมูลบนเครือข่าย
(2) ซ็อกเก็ต ------ ซ็อกเก็ตคือการห่อหุ้มและการประยุกต์ใช้โปรโตคอล TCP/IP (ระดับโปรแกรม)
(3), HTTP ------ HTTP เป็นโปรโตคอลแอปพลิเคชันเลเยอร์ซึ่งส่วนใหญ่จะแก้ไขวิธีการห่อข้อมูล
(4) รุ่นเครือข่ายเจ็ดชั้น --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
เพื่อสรุป: ซ็อกเก็ตคือการห่อหุ้มของโปรโตคอล TCP/IP ซ็อกเก็ตเองไม่ใช่โปรโตคอล แต่เป็นอินเตอร์เฟสการโทร (API)
รูปแบบนี้บางส่วนของอินเทอร์เฟซที่ใช้งานได้พื้นฐานที่สุดที่เรารู้จักเช่นสร้าง, ฟัง, เชื่อมต่อ, ยอมรับ, ส่งอ่านและเขียน ฯลฯ
TCP/IP เป็นเพียงสแต็กโปรโตคอลเช่นเดียวกับกลไกการทำงานของระบบปฏิบัติการจะต้องดำเนินการอย่างละเอียดและยังให้อินเทอร์เฟซการทำงานภายนอก
ในความเป็นจริง TCP ของเลเยอร์การขนส่งขึ้นอยู่กับโปรโตคอล IP ของเลเยอร์เครือข่ายและโปรโตคอล HTTP ของชั้นแอปพลิเคชันจะขึ้นอยู่กับโปรโตคอล TCP ของชั้นการขนส่ง ซ็อกเก็ตเองไม่ใช่โปรโตคอล ดังที่ได้กล่าวมาแล้วจะมีเพียงอินเทอร์เฟซสำหรับการเขียนโปรแกรม TCP หรือ UDP
ประการที่สองสัมผัสกับมัน
โอเคเรามีแนวคิดลองมาเป็นตัวอย่าง:
1. สร้าง Server.js
การคัดลอกรหัสมีดังนี้:
var net = ต้องการ ('net');
var server = net.createserver (ฟังก์ชัน (c) {// การเชื่อมต่อฟัง
console.log ("เซิร์ฟเวอร์เชื่อมต่อ");
c.on ("end", function () {
console.log ("เซิร์ฟเวอร์ถูกตัดการเชื่อมต่อ");
-
c.write ("สวัสดี bigbear!/r/n");
c.pipe (c);
-
Server.Listen (8124, function () {// ฟังฟังฟัง
console.log ("เซิร์ฟเวอร์ผูกพัน");
-
2. สร้าง client.js
การคัดลอกรหัสมีดังนี้:
var net = ต้องการ ('net');
var client = net.connect ({
พอร์ต: 8124
}, function () {// Connect Listener
console.log ("ไคลเอนต์เชื่อมต่อ");
client.write ('สวัสดีที่รัก!/r/n');
-
client.on ("data", function (data) {
console.log (data.toString ());
client.end ();
-
client.on ("end", function () {
console.log ("ลูกค้าตัดการเชื่อมต่อ");
-
วิเคราะห์กันเถอะ:
เซิร์ฟเวอร์ ------ net.createServer สร้างบริการ TCP บริการนี้ถูกผูกไว้ (Server.Listen) บนพอร์ต 8124 หลังจากสร้างเซิร์ฟเวอร์เราจะเห็นฟังก์ชั่นการโทรกลับ
เมื่อเรียกใช้ฟังก์ชันข้างต้นพารามิเตอร์ก็เป็นฟังก์ชันและยอมรับซ็อกเก็ตท่อที่สร้างโดยวิธีอื่นและฟังก์ชั่นของมันสำหรับการโต้ตอบข้อมูล
ลูกค้าจะต้องได้รับการต้อนรับจากลูกค้าเพื่อสร้างมัน หากไม่มีการเข้าถึงไคลเอนต์ไปยังเซิร์ฟเวอร์ในขณะนี้ซ็อกเก็ตนี้จะไม่มีอยู่จริง
ตามชื่อแนะนำ客户端------net.connect เชื่อมต่อกับเซิร์ฟเวอร์ พารามิเตอร์แรกคือวัตถุ พอร์ต (พอร์ต) ถูกตั้งค่าเป็น 8124 ซึ่งเป็นพอร์ตที่เซิร์ฟเวอร์ของเราฟัง เนื่องจากไม่ได้ตั้งค่าพารามิเตอร์โฮสต์ค่าเริ่มต้นคือ localhost (local)
ในเซิร์ฟเวอร์ซ็อกเก็ตเป็นปลายด้านหนึ่งของไปป์ไลน์และในไคลเอนต์ไคลเอนต์เองเป็นปลายด้านหนึ่งของไปป์ไลน์ หากไคลเอนต์หลายตัวเชื่อมต่อกับเซิร์ฟเวอร์เซิร์ฟเวอร์จะสร้างซ็อกเก็ตหลายตัวและซ็อกเก็ตแต่ละตัวสอดคล้องกับไคลเอนต์
ผลการทำงาน:
3. บทนำกรณี
(1) รหัสต่อไปนี้เป็นเพียงการส่งข้อความเซิร์ฟเวอร์ให้กับไคลเอนต์เพื่อทำการสื่อสารทางเดียวจากเซิร์ฟเวอร์ไปยังไคลเอนต์
การคัดลอกรหัสมีดังนี้:
// sever-> การสื่อสารทางเดียวของลูกค้า
var net = ต้องการ ('net');
var chatserver = net.createserver ();
chatserver.on ('การเชื่อมต่อ', ฟังก์ชั่น (ไคลเอนต์) {
client.write ('สวัสดี!/n'); // ข้อมูลเซิร์ฟเวอร์ส่งออกไปยังไคลเอนต์และใช้วิธีการเขียน ()
client.write ('ลาก่อน!/n');
client.end (); // เซิร์ฟเวอร์สิ้นสุดเซสชัน
-
chatserver.listen (9000);
การทดสอบ Telnet: Telnet127.0.0.1: 9000
หลังจากดำเนินการ Telnet ให้เชื่อมต่อกับจุดบริการแสดงความคิดเห็นถึงตัวละครของ HI! ลาก่อน!, และจบโปรแกรมเซิร์ฟเวอร์ทันทีและยุติการเชื่อมต่อ
ถ้าเราต้องการให้เซิร์ฟเวอร์เชื่อมต่อกับข้อมูลกับไคลเอนต์
คุณสามารถฟังเหตุการณ์ Server.data และไม่ยกเลิกการเชื่อมต่อ (หรือจะสิ้นสุดข้อความจากไคลเอนต์ที่ไม่สามารถยอมรับได้ทันที)
(2) ฟังเหตุการณ์ Server.data และไม่ยกเลิกการเชื่อมต่อ (มิฉะนั้นข้อความจากไคลเอนต์จะไม่ได้รับการยอมรับทันที)
การคัดลอกรหัสมีดังนี้:
// ขึ้นอยู่กับอดีตลูกค้าใช้งาน-> การสื่อสารแบบรุนแรงซึ่งเป็นการสื่อสารสองทาง
var net = ต้องการ ('net');
var chatserver = net.createserver ()
clientList = [];
chatserver.on ('การเชื่อมต่อ', ฟังก์ชั่น (ไคลเอนต์) {
// JS สามารถเพิ่มคุณสมบัติลงในวัตถุได้อย่างอิสระ ที่นี่เราเพิ่มแอตทริบิวต์ที่กำหนดเองของชื่อเพื่อระบุไคลเอนต์ (ที่อยู่ + พอร์ตของไคลเอนต์ที่ใช้)
client.name = client.remoteaddress + ':' + client.remoteport;
client.write ('hi' + client.name + '!/n');
clientList.push (ไคลเอนต์);
client.on ('data', function (data) {
ออกอากาศ (ข้อมูลลูกค้า); // ยอมรับข้อมูลจากลูกค้า
-
-
ฟังก์ชั่นออกอากาศ (ข้อความไคลเอนต์) {
สำหรับ (var i = 0; i <clientlist.listing; i+= 1) {
ถ้า (ไคลเอนต์! == ไคลเอนต์ [i]) {
clientList [i] .write (client.name + "พูดว่า" + ข้อความ);
-
-
-
chatserver.listen (9000);
ด้านบนเป็นรหัสที่สมบูรณ์หรือไม่? เราบอกว่ามีปัญหาอื่นที่ไม่ได้นำมาพิจารณานั่นคือเมื่อลูกค้าออกไปแล้วมันจะยังคงอยู่ในรายการลูกค้าซึ่งเห็นได้ชัดว่าเป็นตัวชี้โมฆะ
(3) ประมวลผลไคลเอนต์ลิสต์
การคัดลอกรหัสมีดังนี้:
chatserver.on ('การเชื่อมต่อ', ฟังก์ชั่น (ไคลเอนต์) {
client.name = client.remoteaddress + ':' + client.remoteport
client.write ('hi' + client.name + '!/n');
clientList.push (ไคลเอนต์)
client.on ('data', function (data) {
ออกอากาศ (ข้อมูลไคลเอนต์)
-
client.on ('end', function () {
clientList.splice (clientlist.indexof (ไคลเอนต์), 1); // ลบองค์ประกอบสูตรในอาร์เรย์
-
-
Nodetcpapi ให้เหตุการณ์สุดท้ายแก่เรานั่นคือเมื่อไคลเอนต์ยกเลิกการเชื่อมต่อกับเซิร์ฟเวอร์
(4) เพิ่มประสิทธิภาพการออกอากาศ
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่นออกอากาศ (ข้อความไคลเอนต์) {
var cleanup = []
สำหรับ (var i = 0; i <clientlist.listing; i+= 1) {
ถ้า (ไคลเอนต์! == ไคลเอนต์ [i]) {
if (clientlist [i]. writable) {// ตรวจสอบว่าซ็อกเก็ตเป็นสิ่งที่เขียนได้ก่อน
clientList [i] .write (client.name + "บอกว่า" + ข้อความ)
} อื่น {
cleanup.push (clientlist [i]) // ถ้ามันไม่สามารถเขียนได้ให้รวบรวมและทำลายมัน ก่อนที่จะถูกทำลายซ็อกเก็ต. destroy () จะต้องถูกทำลายโดย API
ClientList [i] .Destroy ()
-
-
} // ลบโหนดที่ตายแล้วออกจากการเขียนลูปเพื่อหลีกเลี่ยงดัชนีลูปทิ้งขยะ
สำหรับ (i = 0; i <cleanup.length; i+= 1) {
clientList.splice (clientlist.indexof (cleanup [i]), 1)
-
-
โปรดทราบว่าเมื่อไม่ได้ทริกเกอร์ "สิ้นสุด" ข้อยกเว้นจะเกิดขึ้นดังนั้นงานการเพิ่มประสิทธิภาพจะเสร็จสิ้น
(5) Netapi ยังมีเหตุการณ์ข้อผิดพลาดเพื่อตรวจสอบข้อยกเว้นของลูกค้า
การคัดลอกรหัสมีดังนี้:
client.on ('ข้อผิดพลาด', ฟังก์ชัน (e) {
console.log (e);
-
สี่มาสรุปกันเถอะ
1. เข้าใจแนวคิดที่เกี่ยวข้องของการเริ่มต้น
2. เข้าใจความสัมพันธ์ระหว่าง HTTP และโมดูลสุทธิ
3. ตามตัวอย่างในบทความนี้โปรดดู API ที่เกี่ยวข้องเพื่อฝึกฝน
4. แนวคิดการสื่อสารระหว่างซ็อกเก็ตไคลเอนต์และเซิร์ฟเวอร์
5. หากคุณสนใจคุณสามารถปรับปรุงตัวอย่างของห้องแชทนั้นได้