Tìm hiểu về websocket với rails
Bài đăng này đã không được cập nhật trong 3 năm
Tìm hiểu về websocket với rails
1.Websocket là gì?
WebSoket là công nghệ hỗ trợ giao tiếp hai chiều giữa client và server bằng cách sử dụng một TCP socket để tạo một kết nối hiệu quả và ít tốn kém.
Thông thường dữ liệu được truyền qua phương thức http sẽ chứa các dữ liệu không cần thiết trong headers của một message. Vì vậy khi truyền dữ liệu sẽ rất chậm. Ví dụ 1 header của một http request thường là hơn 800kb trong khi 1 message của websocket chỉ là 2kb.
Mục đích của giao thức WebSocket là cung cấp thông tin liên lạc hai chiều giữa một khách hàng và một máy chủ mà không cần mở nhiều kết nối vì thế nên truyền gửi message rất nhanh chóng.
Tuy nhiên nó cũng có những nhược điểm như không có phạm vi yêu cầu nào, do không sử dụng header nên nó không có session nào cả. Khi một connect bị ngắt kết nối thỳ các transaction và contest của nó cũng bị hủy bỏ theo.
2. Giao thức bắt tay của websocket
Chúng ta sử dụng 3 events sau:
onopen: Khi websocket đã được mở onmessage: Khi nhận được một message onclose: Khi websocket được đóng lại
Giao thức WebSocket như đã nêu ở trên là giao thứchai chiều qua kết nối TCP duy nhất. Các giao thức bao gồm một cái bắt tay mở mà được giải thích bởi HTTP như là một yêu cầu nâng cấp tiếp theo là khung thông điệp cơ bản, lớp trên TCP. Các giao thức sử dụng mô hình bảo mật dựa trên nguồn gốc. Mục đích của giao thức WebSocket là cung cấp thông tin liên lạc hai chiều giữa một khách hàng và một máy chủ mà không cần mở nhiều kết nối. Một WebSocket hỗ trợ cả hai chuỗi UTF-8 và khung hình nhị phân
3. Gem websocket-rails
Bắt đầu từ rails 4 trở đi đã hỗ trợ websocket. Ta tìm hiểu gem websocket-rails với 3 phần:
1. Subscribe Events to Actions
Khi install gem websocket-rails và chạy sẽ tạo ra một file event.rb vào trong thư mục config để trỏ các event đến chính xác action trong controller. Ta dùng hàm subscribe
để định nghĩa như sau:
subscribe :event_name, :to => EventController, :with_method => :action_method
or
subscribe :event_name, 'event#action_method'
Nó sẽ điều hướng đến event.trigged từ javascript client như sau:
dispatcher.trigger('event_name', object_to_send);
2. WebsocketRails Controllers
Ta có thể khơi tạo 1 session trong suốt quá trình connection được mở cho đến khi đóng:
def initialize_session
# perform application setup here
controller_store[:message_count] = 0
end
Trong controller dùng hàm send_message để trigger event đến 1 kênh nào đó Ví dụ:
new_message = {:message => 'this is a message'}
send_message :event_name, new_message
Muốn gửi đến một user cụ thể ta có thể dùng:
WebsocketRails.users[myUser.id].send_message('new_notification', {:message => 'you\'ve got an upvote '})
Hoặc dùng hàm broadcast để gửi message đến toàn bộ client đang subscribe kênh:
broadcast_message :new_comment, new_comment
3. Websocket client với javascript
Dưới client để tạo 1 connection ta dùng hàm ví dụ như sau: var dispatcher = new WebSocketRails('localhost:3000/websocket'); function on_open() sẽ được chạy ngay sau khi một connection được khởi tạo Để trigger một event từ server ta dùng như sau:
var comment = {
title: 'This post was awful',
body: 'really awful',
post_id: 9
}
dispatcher.trigger('comments.create', comment);
Dữ liệu sẽ được gửi lên server theo event comment.create
.
Nhận message tử server trả lại bằng hàm bind. ví dụ:
dispatcher.bind('comments.new', addCommentToDom);
4. Standalone Server Mode
Websocket có thể chạy được với eventmachine như thin, puma nhưng để chạy được với non-eventmachine như unicorn hoặc phusion ta cần bật standalone mode. Việc này rất có ý nghĩa khi deploy trên server.
Để bật standalone mode ta config:
config.standalone = true
Mặc định standalone mode sẽ chạy cổng 3001 nên tao có thể config chính xác cổng chạy websocket như sau:
config.standalone_port = 3245
Có thể tham khảo thêm tại https://github.com/websocket-rails/websocket-rails/wiki/Standalone-Server-Mode
4. Demo một ứng dụng chat group dùng websocket
ý tưởng chat room đơn giản sử dụng gem websocket-rails. Bỏ qua phần signup, signin .. sử dụng devise. Ta vào luôn phần chính. Ở file event.rb ta subscribe 3 event sau:
subscribe :client_connected, :to => ChatController, :with_method => :user_connected
subscribe :new_message, :to => ChatController, :with_method => :incoming_message
Với client_connected sẽ khởi tạo 1 socket connection. new_message sẽ target đến incoming_message có chức năng gửi toàn bộ message đến 1 kênh nào đó
Vì vậy code controller sẽ như sau:
def user_connected
p 'user connected'
send_message :user_info, {:user => current_user.screen_name}
end
def incoming_message
broadcast_message :new_message, {:user => current_user.screen_name, :text => message[:text]}
end
5. Kết luận
Tài liệu tham khảo: https://github.com/websocket-rails/websocket-rails http://blog.rikkeisoft.com/seminar-gioi-thieu-ve-websocket-va-node-js/
All rights reserved