מדריך Node.js: איך עובדים עם sockets

במאמר הקודם דיברנו על streams, במאמר הזה אנו נדבר על Sockets – או יותר נכון האימפלמנטציה של השרת שאמור לתמוך בזה!

אז מה זה Socket? מדובר בצורת תקשורת שאפשר להפעיל אותה בין שני מחשבים (שני שרתים לצורך העניין) כדי להעביר מיעד. sockets משתמשים ב-TCP על מנת להעביר נתונים. בשונה מבקשות HTTP רגילות, עם sockets אנו יכולים ליצור תקשורת שבה שני הצדדים יכולים לשלוח מידע באופן שווה. בניגוד, למשל, ל-HTTP, שם רק ה-client יכול ליצור בקשות.
למשל, אם אני עובד עם AJAX מול שרת מרוחק, הוא יחזיר לי מידע רק אם אני שולח לו בקשה מפורשת דרך AJAX. אם אני עובד עם Socket, אז ברגע שה-client מתחבר, גם השרת וגם ה-client יכולים ליצור בקשות. כל בקשה ב-Socket מגיע כשהיא הרבה יותר רזה מבקשת HTTP – כלומר חוץ מבקשת החיבור הראשונית אין לנו header.
אם יש לנו שני שרתים שצריכים לקיים תקשורת אחד עם השני – socket היא דרך נהדרת לקיום תקשורת כזו. כאשר התקשורת יכולה להעביר כל סוג נתונים שהוא.

כאשר אנו מדברים על Socket ב-Node.js אנחנו יכולים להיות השרת – זה שיושב ומחכה לבקשות. או הלקוח – זה שיוזם את הבקשה. המודול שיוצר הן את השרת והן את הלקוח הוא net.

יצירת שרת מאוד דומה לשרת http. זה נראה משהו כזה:


var net = require('net');
var server = net.createServer(function(socket) { //'connection' listener
    console.log('server connected');
    socket.on('end', function() {
        console.log('server disconnected');
    });
    socket.write('hello\r\n');
    socket.pipe(socket);
});
server.listen(1311, function() { //'listening' listener
    console.log('server bound');
});

את הקוד לעיל, אגב, שיניתי מעט אבל הוא מתבסס על הדוגמה שיש במתודת createServer בדוקומנטציה.

מה הולך פה? מאוד דומה לשרת רגיל – רק שבמקום request אני מעביר אובייקט socket שדרכו מתבצעת התקשורת. במקרה הזה מדובר בשרת משדר בלבד. הוא כותב רק hello.

איך נבדוק את זה? בדיוק בשביל זה יש לנו את פקודת telnet בחלונות ובלינוקס. נקליד את הפקודה הבאה:


telnet 127.0.0.1 1311

ברגע שנתחבר, נוכל לראות ‘hello’.

עוד משהו נחמד שאפשר לראות זה שאני משתמש פה ב- pipe ובמקרה הזה ה-socket הוא ה-writable וה-readable אז זה נראה קצת מצחיק. אבל אנחנו משתמשים בו כדי לבצע streaming.

בדוגמה הזו אני רק משדר מידע. איך אקבל מידע? בדוקומנטציה נראה שיש אירוע ל-socket של קבל מידע בשם data, אם אתחבר אליו אני יכול לקבל גישה בקלות למידע. הנה דוגמה לשרת זהה לדוגמה שלעיל שמשדר חזרה את המידע:


var net = require('net');
var server = net.createServer(function(socket) { //'connection' listener
    console.log('server connected');
    socket.on('end', function() {
        console.log('server disconnected');
    });

    socket.on('data', function(data) {
        console.log('data received:'+data);
        socket.write('data is:'+data);
        socket.pipe(socket);
    });


});
server.listen(1311, function() { //'listening' listener
    console.log('server bound');
});

ואם אני רוצה להתחבר לשרת אחר? במקרה הזה אני צריך ליצור client חדש שיוצר קשר ומעביר דרכו את המידע. במקרה הזה אני פשוט יוצר client חדש בדיוק כפי שיש בדוקומנטציה. ברגע שהוא נוצר אני משדר את המידע. פשוט להסתכל בדוגמה:



var client = new net.Socket();
client.connect(1311, '127.0.0.1', function() {
    console.log('Connected');

    client.write('Hello, server! Love, Client.');
    client.pipe(client);
});

client.on('data', function(data) {
    console.log('Received: ' + data);
    client.destroy(); // kill client after server's response
});

client.on('close', function() {
    console.log('Connection closed');
});

הדוגמה, אגב, נקלחה במלואה עם שינוי קל (פשוט הוספתי את ה-pipe) מה-Gist הזה.

אז ככה אני יוצר שרת וככה אני יוצר קליינט. אם אתם גם מתרגלים את הקוד או לפחות מעתיקים אותו למכונה שלכם ומשנים אותו במעט, אפשר לראות שכבר הקוד של Node.js מתחיל להראות קל יותר ואינטואיטיבי יותר. נכון, כמה מאמרים ודוגמאות קוד פשוטות הן לא תחליף לניסיון משמעותי, אבל אני מקווה שהקוד מתחיל להראות הגיוני והשפה של Node.js – כלומר יצירת אובייקט והתחברות לאירועים נראית יותר הגיונית.

שימו לב שכאשר אנו מדברים על Sockets במאמר הזה – אנחנו לא מדברים על Web Sockets שהוא אימפלמנטציה של Sockets בסביבת דפדפן. למי שלא מכיר את Web Sockets – אני ממליץ בחום רב לקרוא את המאמר על Web Sockets שכתבתי ומסביר איך זה עובד מבחינת הפרונט אנד. למי שכן מכיר: זה לא Web Sockets, אם אנחנו רוצים לממש Web Sockets אז צריך להשתמש בשרת http כדי לממש את הפרוטוקול של ה-Hand Shake של Web Sockets או (מה שכולם עושים) להשתמש במודול חיצוני כדי לעשות את זה.

במאמר הבא אנו נדבר על npm.

כדאי תמיד להשאר מעודכנים! הרשמו לעדכונים של האתר במייל! - המייל יישלח כל יום ראשון בעשר בבוקר ויכיל אך ורק את המאמרים שהתפרסמו באינטרנט ישראל. ללא ספאם, ללא הצפות, ללא בלגנים. אם יש לכם טלגרם, בדקו את ערוץ הטלגרם של האתר שבו אני מעדכן על פוסטים חדשים 🙂
למאמר הקודם בסדרת המדריכים על Node.js
למאמר הבא בסדרת המדריכים על Node.js

אהבתם? לא אהבתם? דרגו!

לא אהבתי בכלללא אהבתיבסדראהבתיאהבתי מאוד (2 הצבעות, ממוצע: 5.00 מתוך 5)

תגיות: פורסם בקטגוריה: Node.js

אל תשארו מאחור! יש עוד מה ללמוד!

2 comments on “מדריך Node.js: איך עובדים עם sockets
  1. Yaniv הגיב:

    מה היה קורה אלאמלא היית מוסיף את הpipe לדוגמא מהגיסט?
    מה קורה במילים אחרות אם עושים write ללא pipe אחריו?

  2. רן כהן הגיב:

    למה צריך את ;(client.pipe(client? אם אני מוריד אותו הכל מודפס יופי, אבל אם אני משאיר אותו הוא גורם לשגיאה (בהרצה מ WebStorm):
    events.js:160
    throw er; // Unhandled ‘error’ event
    ^

    Error: This socket is closed
    at Socket._writeGeneric (net.js:680:19)
    at Socket._write (net.js:731:8)
    at doWrite (_stream_writable.js:334:12)
    at writeOrBuffer (_stream_writable.js:320:5)
    at Socket.Writable.write (_stream_writable.js:247:11)
    at Socket.write (net.js:658:40)
    at Socket.ondata (_stream_readable.js:555:20)
    at emitOne (events.js:101:20)
    at Socket.emit (events.js:188:7)
    at readableAddChunk (_stream_readable.js:176:18)