Socket - IO và chat app
Hi các bạn! Ở bài trước mình đã overview về Node Js. Và ở phần này mình sẽ giới thiệu thêm cho các bạn về một chủ đề khá thú vị đó là SocketIO. Cùng mình làm demo cho sống động nhé Sơ lược về Socket và SocketIO : Trước tiên, Socket là 1 công nghệ. Đừng nhầm lẫn giữa Socket.IO và Socket. ...
Hi các bạn! Ở bài trước mình đã overview về Node Js. Và ở phần này mình sẽ giới thiệu thêm cho các bạn về một chủ đề khá thú vị đó là SocketIO. Cùng mình làm demo cho sống động nhé
Sơ lược về Socket và SocketIO :
Trước tiên, Socket là 1 công nghệ. Đừng nhầm lẫn giữa Socket.IO và Socket. Socket.IO không phải là mô hình Socket duy nhất hiện nay, và cũng không phải là mô hình web socket duy nhất hiện nay. Socket là cách bạn tổ chức mô hình client-server để một trong 2 bên luôn trong tình trạng sẵn sàng trả lời bên kia và ngược lại. Để đảm bảo việc này, kết nối giữa Client và Server phải ở trạng thái “keep-alive” và phải luôn xảy ra quá trình đồng bộ giữa Client-Server. Socket sẽ mang lại khả năng trả lời tức thì từ một trong 2 bên khi bên kia đưa ra một sự kiện, thay vì phải thực thi lại một loạt các thủ tục kết nối phức tạp như trước, và ứng dụng của bạn sẽ trở thành ứng dụng thời gian thực ví dụ: Yahoo Messenger, Skype v.v… đều là các ứng dụng được xây dựng theo mô hình Socket.
Trong lập trình web trước đây, việc xây dựng client-server theo mô hình socket phải thông qua các phần mềm thứ 3. Vì mô hình socket không phù hợp với các ngôn ngữ lập trình Server như: PHP, ASP.NET, JSP v.v… Các ngôn ngữ này luôn làm việc theo cách: Die ngay connection khi Server trả lời Client xong. Tuy nhiên, mình nhấn mạnh: Chúng ta có thể làm được web-socket với bất kỳ ngôn ngữ lập trình nào. Chỉ có điều, với các ngôn ngữ cũ, việc làm này cần bạn phải am hiểu các giao thức http, tcp; hiểu thế nào là 1 request header, v.v…
Node.js là một ngôn ngữ mới, xây dựng thuần túy bằng javascript. Đây là một điểm lợi thế của Node.js để lập trình web-socket:
Thứ nhất: javascript là ngôn ngữ lập trình hướng sự kiện, mà trong lập trình thời gian thực, cách tiếp cận bằng lập trình sự kiện là cách tiếp cận khôn ngoan nhất.
Thứ hai: Node.js chạy non-blocking việc hệ thống không phải tạm ngừng để xử lý xong một request sẽ giúp cho server trả lời client gần như ngay tức thì.
Thứ ba: lập trình socket yêu cầu bạn phải xây dựng được mô hình lắng nghe - trả lời từ cả 2 bên. Nói khác đi, vai trò của client và server phải tương đương nhau, mà client thì chạy bằng javascript, nên nếu server cũng chạy bằng javascript nữa, thì việc lập trình sẽ dễ dàng và thân thiện hơn.
Chính vì những đặc điểm này, socket.io ra đời. Tuy nhiên, khi bạn thực sự am hiểu về Node.js, http request header, bạn hoàn toàn có thể viết một socket cho riêng mình.
Demo Chat app
Sau khi đã tìm hiểu về node.js và socket.io thì bây giờ, chúng ta sẽ ứng dụng để làm 1 demo nhỏ. Trong hướng dẫn này chúng ta sẽ tạo một ứng dụng chat cơ bản.
Giới thiệu
Viết một ứng dụng chat với hầu hết các web application như LAMP(PHP) là điều rất khó khăn. Nó đòi hỏi việc polling server cho những thay đổi, theo dõi timestamps và nó chậm hơn rất nhiều so với mong đợi của người sử dụng.
Socket có thể giải quyết các vấn đề xung quanh, nhưng vấn đề mà hầu hết các hệ thống chat thời gian thực được kiến trúc. Cung cấp kênh thông tin liên lạc giữa client và server.
Điều này có nghĩa là server có thể push message đến client, bất cứ khi nào bạn viết một message, ý tưởng là client sẽ nhận được message và push nó đến tất cả các client đang có kết nối khác.
The web framework
Mục tiêu đầu tiên là thiết lập 1 trang html, nó sẽ chứa 1 form để nhập nội dung message và nơi chứa list message chat giữa các client. Chúng ta sẽ sử dụng Express framework để thực hiện việc này. Hãy chắc chắn rằng NodeJS đã được cài đặt trên máy của bạn nhé.
Đầu tiên chúng ta sẽ tạo file package.json nơi sẽ mô tả project của chúng ta. Chúng ta sẽ tạo một thư mục cho project này (chẳng hạn tôi đặt là chat-example).
{ "name": "chat-example", "version": "1.0.0", "description": "chat-examole", "main": "index.js", "scripts": { "test": "echo "Error: no test specified" && exit 1" }, "author": "ThanhManCi", "license": "ISC", "dependencies": { "express": "^4.15.2", "socket.io": "^2.0.4" } }
- Express khởi tạo app như 1 function handle mà bạn có thể cung cấp cho máy chủ HTTP
- Chúng ta định nghĩa function get, sử lý xự kiện khi chúng ta di chuyển đến trang home của website.
- Tạo http server lắng nghe trên cổng 3000 Bây giờ, nếu chúng ta chạy file index.js, chúng ta sẽ thấy như sau:
Và nếu chúng ta chạy trên trình duyệt với đường dẫn http://localhost:3000 sẽ có dòng chữ mà lập trình viên nào cũng đều biết đúng không nào ^^
- Serving HTML
Để ứng dụng của chúng ta dễ hình dung hơn. Tôi sẽ tạo riêng 1 file html cho phần giao diện.
Trong file index.js chúng ta sẽ thay thế đoạn code này, để gọi đến trang index.html
app.get('/', function(req, res){ res.sendFile(__dirname + '/index.html'); });
index.html thì sẽ như sau:
<html> <head> <title>Socket.IO chat</title> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script> </head> <body> <label for="message" class="h4" style="margin-top: 20px;">Message:</label> <ul id="messages" style="height: 600px; border: solid 1px #cecece;"></ul> <div class="form-group"> <textarea id="m" class="form-control" rows="5" placeholder="Enter your message" required></textarea> </div> <button type="submit" id="form-submit" class="btn btn-success btn-lg pull-right ">Submit</button> </body> </html>
Kết quả sẽ như nhau:
- Integrating Socket.IO Socket.IO gồm có hai phần:
- Một Server tích hợp(hoặc gắn kết) các Node.js HTTP Server: socket.io
- Một thư viện client mà tải ở phía trình duyệt: socket.io-client Trong development, socket.io phục vụ các client tự động cho chúng ta, như chúng ta sẽ thấy sau đây, vì vậy bây giờ chúng ta chỉ cần cài đặt một module:
npm install --save socket.io
Bây giờ chúng ta sẽ sửa file index.js
var app = require('express')(); var http = require('http').Server(app); var io = require('socket.io')(http); app.get('/', function(req, res){ res.sendFile(__dirname + '/index.html'); }); io.on('connection', function(socket){ console.log('a user connected'); }); http.listen(3000, function(){ console.log('listening on *:3000'); });
Tiếp theo, add nội dung dưới đây vào file index.html trước thẻ
<script src="/socket.io/socket.io.js"></script> <script> var socket = io(); </script>
Đó là tất cả những gì cần thiết để load các socket.io-client, và sau đó là kết nối. Bây giờ nếu có một người dung nào kết nối đến server. Một thông báo sẽ xuất hiện ở console “a user connected”.
Thử mở nhiều tab, bạn sẽ thấy nhiều thông điệp. Mỗi soket cũng có sự kiến ngắt kết nối đặc biệt.
io.on('connection', function(socket){ console.log('a user connected'); socket.on('disconnect', function(){ console.log('user disconnected'); }); });
- Emitting events Ý tưởng chính là khi người dung nhập một tin nhắn và nhấn Enter/Send SocketIO sẽ bắt sự kiện này và gửi lên seser xử lý, sau đó trả về lại cho người dung, nhưng người đang connect đến server nội dung message. Bây giờ chúng ta sẽ sửa file index.html như bên dưới
<script src="/socket.io/socket.io.js"></script> <script src="https://code.jquery.com/jquery-1.11.1.js"></script> <script> $(function () { var socket = io(); $('form').submit(function(){ socket.emit('chat message', $('#m').val()); $('#m').val('); return false; }); }); </script>
Trong file index.js, chúng ta them xử lý out message cho client
io.on('connection', function(socket){ socket.on('chat message', function(msg){ console.log('message: ' + msg); }); });
- Broadcasting Mục tiêu tiếp theo là để chúng ta phát ra sự kiện từ máy chủ đến các người sử dụng còn lại.
Để gửi một sự kiện để tất cả mọi người, Socket.IO cho chúng ta io.emit:
io.emit('some event', { for: 'everyone' });
Nếu bạn muốn gửi message đến tất cả các client, ngoại trừ người nào đó
io.on('connection', function(socket){ socket.broadcast.emit('hi'); });
Trong trường hợp này, để đơn giản, tôi gửi đến tất cả các client kể cả người gửi.
io.on('connection', function(socket){ socket.on('chat message', function(msg){ io.emit('chat message', msg); }); })
Về phía client, tôi sẽ tạo một xử lý bắt sự kiến mà server trả message về.
<script> $(function () { var socket = io(); $('form').submit(function(){ socket.emit('chat message', $('#m').val()); $('#m').val('); return false; }); socket.on('chat message', function(msg){ $('#messages').append($('<li>').text(msg)); }); }); </script>
Và cuối cùng ứng dụng chat đơn giản của chúng ta đã hoàn thành. Cùng xem kết quả nhé. Toàn bộ demo mình để ở đây
Vậy là chúng ta đã có 1 ứng dụng chat khá là đơn giản phải không nào. Hẹn gặp lại các bạn ở những bài sau