Tóm Tắt
Websocket Server
Mình sẽ tạo mới một Maven project để kiến thiết xây dựng Websocket server :
Bạn đang đọc: Websocket với Socket.IO Java – Hướng Dẫn Java
Để thích hợp với thư viện Socket. IO-client Java, tất cả chúng ta sẽ sử dụng Socket. IO Java version 3. x như sau :
12345 |
io.socket |
socket.io – server
3.0.2
Trong ví dụ này, mình sẽ start một Websocket server sử dụng Socket. IO Java với một embedded Jetty server :
12345 |
org.eclipse.jetty |
jetty-server
9.4.46. v20220331
Khi một HTTP request tới Jetty server này, tất cả chúng ta sẽ tăng cấp HTTP connection lên thành Websocket connection sử dụng Jetty Websocket server :
12345 |
org.eclipse.jetty.websocket |
websocket-server
9.4.46. v20220331
và sử dụng Socket. IO Java để handle connection này với Jetty WebSocket adapter module :
12345 |
io.socket |
engine.io – server-jetty
5.0.1
Bây giờ, tất cả chúng ta sẽ đi vào implement Websocket server những bạn nhé !
Chúng ta sẽ cần khởi tạo đối tượng SocketIoServer của Socket.IO Java để integrate với embedded Jetty server trước.
Để khởi tạo đối tượng người dùng của class SocketIoServer này, tất cả chúng ta cần có đối tượng người tiêu dùng EngineIoServer .
EngineIoServer là một class từ thư viện Engine. IO Java, một thư viện implement kênh tiếp xúc 2 chiều giữa client và server cross-browser / cross-device .
Để có đối tượng người tiêu dùng EngineIoServer thì tất cả chúng ta cần đối tượng người tiêu dùng EngineIoServerOptions. Chúng ta hoàn toàn có thể khởi tạo đối tượng người dùng EngineIoServerOptions này với thông số kỹ thuật mặc định sử dụng phương pháp static newFromDefault ( ) của class EngineIoServerOptions, như sau :
1 |
EngineIoServerOptionsengineIoServerOptions=EngineIoServerOptions.newFromDefault(); |
Một thông số kỹ thuật mặc định mà những bạn cần chú ý quan tâm là thông số kỹ thuật về CORS ( Cross-origin resource sharing ). Các bạn hoàn toàn có thể tìm hiểu và khám phá thêm về CORS trong bài viết của mình về Cấu hình Web Origin trong Keycloak. Mặc định thì tổng thể những origin được được cho phép, những bạn hoàn toàn có thể restrict list origin lại bằng cách sử dụng phương pháp setAllowedCorsOrigins ( ) của đối tượng người tiêu dùng EngineIoServerOptions nếu muốn .
Sau khi đã có đối tượng người dùng EngineIoServerOptions, tất cả chúng ta hoàn toàn có thể khởi tạo đối tượng người dùng EngineIoServer như sau :
1 |
EngineIoServerengineIoServer=newEngineIoServer(engineIoServerOptions); |
Và đối tượng người dùng SocketIoServer từ đối tượng người dùng EngineIoServer :
1 |
SocketIoServersocketIoServer=newSocketIoServer(engineIoServer); |
Sau khi đã có đối tượng SocketIoServer, chúng ta sẽ thêm code để start một embedded Jetty server:
1 |
Serverserver=newServer(newInetSocketAddress(” localhost “,8080)); |
Vì khi một Socket. IO client connect tới Socket. IO Websocket server, nó sẽ request tới server, mặc định với context path là “ / socket.io ” nên tất cả chúng ta cần thêm một servlet để handle cho context path này .
12345678 |
ServletContextHandlerservletContextHandler=newServletContextHandler(ServletContextHandler.SESSIONS); servletContextHandler.addServlet(newServletHolder(newHttpServlet(){ @ Override protectedvoidservice(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException{ engineIoServer.handleRequest(request,response); } }),” / socket.io/ * “); |
Như những bạn thấy, mình khởi tạo một đối tượng người dùng ServletContextHandler và thêm mới một servlet để handle cho toàn bộ những request mở màn với “ / socket.io ”. Tất cả những request khởi đầu với “ / socket.io ” này sẽ được tăng cấp từ HTTP connection lên Websocket connection sử dụng đoạn code sau :
123 |
WebSocketUpgradeFilterwebSocketUpgradeFilter=WebSocketUpgradeFilter.configureContext(servletContextHandler); webSocketUpgradeFilter.addMapping(newServletPathSpec(” / socket.io/ * “),(servletUpgradeRequest, servletUpgradeResponse)->newJettyWebSocketHandler(engineIoServer)); |
Đối tượng EngineIoServer của thư viện Engine. IO Java như mình có nói ở trên, đảm nhiệm việc communication 2 chiều giữa client và server, do đó nó sẽ handle toàn bộ request từ client cho context path “ / socket.io ” này .
Sau khi đã thông số kỹ thuật xong cho đối tượng người dùng ServletContextHandler, tất cả chúng ta cần thêm nó vào handler list của embedded Jetty server :
1 |
server.setHandler(servletContextHandler); |
Như vậy thì tất cả chúng ta đã triển khai xong việc integrate Socket. IO Java với embedded Jetty server. Các bạn cần start embedded Jetty server sử dụng phương pháp start ( ) của đối tượng người tiêu dùng Server như sau :
1 |
server.start(); |
Giờ thì tất cả chúng ta hoàn toàn có thể sử dụng đối tượng người tiêu dùng SocketIoServer để gửi và nhận message với client .
Các bạn hoàn toàn có thể tạo mới một Namespace để thao tác. Đoạn code bên dưới sẽ in ra dòng log “ Client … has connected. ” khi client connect tới namespace “ / ” :
12345678 |
SocketIoNamespacens=socketIoServer.namespace(” / “); ns.on(” connection “,newEmitter.Listener(){ @ Override publicvoidcall(Object…args){ SocketIoSocketsocket=(SocketIoSocket)args[0]; System.out.println(” Client “+socket.getId()+” has connected. “); } }); |
Websocket Client
Mình cũng tạo một Maven project để thiết kế xây dựng một client application connect tới Websocket server mà tất cả chúng ta đã chạy ở trên :
với Socket. IO-client Java dependency như sau :
12345 |
io.socket
socket.io-client
2.0.1 |
Sử dụng một trong những phương pháp static socket ( ) định nghĩa trong class IO của Socket. IO-client Java, những bạn hoàn toàn có thể tạo mới đối tượng người tiêu dùng Socket client như sau :
12345678 |
URIuri=URI.create(” http://localhost:8080 “); / / @ formatter : off IO.Optionsoptions=IO.Options.builder() .build(); / / @ formatter : on Socketsocket=IO.socket(uri,options); |
Tham số của phương pháp socket ( ) mà mình sử dụng ở trên lần lượt là URI của Websocket server và những option của client khi connect tới Websocket server này .
Chúng ta hoàn toàn có thể in ra dòng chữ “ Connected to server ” khi connect tới Websocket server mà mình đã start ở trên như sau :
12345678 |
socket.on(Socket.EVENT_CONNECT,newEmitter.Listener(){ @ Override publicvoidcall(Object…args){ System.out.println(” Connected to server “); } }); socket.connect(); |
Kết quả :
Phía Websocket server, các bạn cũng sẽ thấy dòng chữ sau được in ra như sau:
Gửi message từ client tới Websocket server
Sau khi liên kết với Websocket server, client hoàn toàn có thể gửi một message tới server sử dụng phương pháp emit ( ), ví dụ như sau :
1 |
socket.emit(” message “,” Hello World “); |
Tham số thứ nhất của phương pháp emit ( ) là tên sự kiện còn tham số thứ hai là data sẽ gửi tới sự kiện này. Trong ví dụ này, mình chỉ đơn thuần là gửi một message “ Hello World ” .
Ở phía Websocket server thì những bạn hoàn toàn có thể subscribe vào sự kiện trên để nhận data. Chúng ta phải sử dụng đối tượng người tiêu dùng của class SocketIoSocket gắn với mỗi Websocket connection để làm điều này. Ví dụ để nhận message được emit từ client ở trên, những bạn hoàn toàn có thể thêm code trong phần sự kiện “ connection ” như sau :
123456789101112131415 |
SocketIoNamespacens=socketIoServer.namespace(” / “); ns.on(” connection “,newEmitter.Listener(){ @ Override publicvoidcall(Object…args){ SocketIoSocketsocket=(SocketIoSocket)args[0]; System.out.println(” Client “+socket.getId()+” has connected. “); socket.on(” message “,newEmitter.Listener(){ @ Override publicvoidcall(Object…args){ System.out.println(” [ Client “+socket.getId()+” ] “+args[0]); } }); } }); |
Kết quả khi tất cả chúng ta chạy lại Websocket server và sau đó là client như sau :
Gửi message từ Websocket server tới client
Để gửi message từ Websocket server tới client tất cả chúng ta cũng sử dụng đối tượng người dùng của class SocketIoSocket với phương pháp send ( ). Ví dụ :
1234567891011121314151617 |
SocketIoNamespacens=socketIoServer.namespace(” / “); ns.on(” connection “,newEmitter.Listener(){ @ Override publicvoidcall(Object…args){ SocketIoSocketsocket=(SocketIoSocket)args[0]; System.out.println(” Client “+socket.getId()+” has connected. “); socket.on(” message “,newEmitter.Listener(){ @ Override publicvoidcall(Object…args){ System.out.println(” [ Client “+socket.getId()+” ] “+args[0]); } });
socket.send(” hello “,” Hello from Websocket server “); } }); |
Ở phía client, tất cả chúng ta hoàn toàn có thể subscribe vào sự kiện này để nhận data từ Websocket server, ví dụ như sau :
123456 |
socket.on(” hello “,newEmitter.Listener(){ @ Override publicvoidcall(Object…args){ System.out.println(args[0]); } }); |
Kết quả :
Xem thêm: Hướng dẫn và ví dụ Java Reflection
Source: https://final-blade.com
Category: Kiến thức Internet