ConnectionRelay: Công cụ hữu ích giúp chuyển tiếp gói tin qua Socket
Thực tế, trong nhiều trường hợp bạn cần chuyển tiếp gói tin nhận được từ kết nối này sang kết nối khác, sau đó gói tin phản hồi sẽ được gửi trả lại cho kết nối ban đầu. Có nhiều công cụ giúp bạn làm việc này, trong bài này tôi xin giới thiệu công cụ đơn giản dễ sử dụng ConnectionRelay. Và tôi cũng public mã nguồn của nó để các bạn có thể tìm hiểu và nâng cấp nó nếu cần.
Contents
Mô hình hoạt động của ConnectionRelay
Khi hoạt động, dựa vào cấu hình, ConnectionRelay có thể khởi tạo 01 hoặc nhiều RelaySession, mỗi RelaySession sẽ thực hiện quản lý một kết nối cần chuyển tiếp. Mô hình hoạt động như ảnh dưới:
Theo như ảnh trên, ConnectionRelay khởi tạo "Relayession 01", RelaySession 01 sẽ thực hiện mở ServerSocket và thực hiện lắng nghe ở Port 01 để chờ kết nối từ máy A (Đóng vai trò là Client) và chuyển tiếp bản tin tới máy B (Đóng vai trò là Server) ở Port 02:
- 1 - Client A kết nối tới ConnectionRelay thông qua RelaySession 01. Sau khi kết nối xong, Client A sẽ gửi các gói tin sang cho ConnectionRelay.
- 2 - ConnectionRelay thực hiện kết nối tới Server B, khi kết nối thành công sẽ lưu giữ lại kết nối này. Mỗi khi ConnectionRelay nhận được gói tin từ Client A thông qua RelaySession 01, sẽ gửi lại gói tin này sang Server B thông qua kết nối này.
- 3 - Server B nhận được gói tin thực hiện xử lý và gửi trả lại gói tin phản hồi tới ConnectionRelay thông qua RelaySession 01.
- 4 - ConnectionRelay nhận được gói tin phản hồi sẽ gửi trả lại Client A.
=> Như vậy thay vì kết nối trực tiếp từ Client A sang Server B thì có thể kết nối thông qua máy trung gian có cài đặt ConnectionRelay.
Cấu hình và chạy ConnectionRelay
Để chạy ứng dụng, bạn tải bản chạy từ địa chỉ: File:ConnectionRelay.zip
Đây là bản chạy trực tiếp, cấu trúc thư mục như sau:
Để chạy ứng dụng bạn thực hiện như sau:
- B1: Mở tệp "etc/app.properties" để cấu hình các RelaySession. Tệp này như sau:
# =================================================
# Relay configuration
# =================================================
# Connections
relay.connection.max=2
# Relay sessions. Format: relay_name_1:local_port_1:remote_address_1:remote_port_1; relay_name_2:local_port_2:remote_address_2:remote_port_2;...
relay.sessions = gmail-smtp:8888:smtp.gmail.com:465
Trong tệp này chỉ có hai cấu hình bạn cần sửa:- relay.connection.max: Số connection tối đa cho phép trên một RelaySession. Tùy từng trường hợp và cấu hình server mà thực hiện cấu hình hợp lý.
- relay.sessions: Chứa thông tin các RelaySession trong đó:
- Mỗi RelaySession theo định dạng "relay_name:local_port:remote_address:remote_port". Ví dụ: gmail-smtp:8888:smtp.gmail.com:465
- Nếu có nhiều RelaySession thì các RelaySession phân cách nhau bởi dấu chấm phẩy. Ví dụ: gmail-smtp:8888:smtp.gmail.com:465;yahoo-stmp:8889:plus.smtp.mail.yahoo.com:465
- B2: Khởi chạy ứng dụng:
- Trên Windows:
- B1: Mở "Command Prompt" và chuyển đến thư mục bin.
- B2: Đánh lệnh sau để chạy:
start.bat
- Trên Linux/Ubuntu:
- B1: Bật "Terminal" và chuyển đến thư mục bin.
- B2: Đánh lệnh sau để chạy:
./start.sh
- Trên Windows:
- B3: Sau khi chạy xong bạn sẽ thấy trên Console hiển thị log như sau:
Nếu bạn muốn chạy dưới dạng Service, bạn có thể tích hợp với Java Service Wrapper. Các bạn có thể download bản tích hợp "Java Service Wrapper" tại địa chỉ: File:ConnectionRelay-Service.zip
Các bước thực hiện để chạy như sau:
- Trên Windows:
- B1: Mở tệp "start-app.bat" trong thư mục bin. Bạn nhớ thiết lập biến JAVA_HOME ở dòng thứ tư tới đúng đường dẫn tới thư mục JDK/JRE 32 bit cài đặt trên máy. Để chạy được trên Windows bạn phải cài JDK hoặc JRE 32 bit, vì Java Service Wrapper bản Community không hỗ trợ Windows 64 bit.
- B2: Mở "Command Prompt" và chuyển đến thư mục bin.
- B3: Đánh lệnh sau để chạy:
start-app.bat start - B4: Xem log trong tệp "logs/connection-relay.log"
- Trên Linux/Ubuntu:
- B1: Bật "Terminal" và chuyển đến thư mục bin.
- B2: Đánh lệnh sau để chạy:
./start-app start
Starting Connection Relay Application...
Waiting for Connection Relay Application....
running: PID:16977
Đánh lênh sau để stop:
./start-app stop - B3: Trường hợp bạn muốn xem log thì đánh lệnh sau:
tail -f ../logs/connection-relay.log
Hướng dẫn cấu hình trong một số trường hợp phát sinh thực tế
Dưới đây là một số trường hợp sử dụng ConnectionRelay trong thực tế:
Trường hợp 1: Kết nối từ máy Client tới máy chủ thông qua một máy khác
Trong một số môi trường bảo mật, bạn muốn kết nối đến server ở cổng nào đó bạn phải làm thủ tục xin kết nối khá mất thời gian. Khi làm thủ tục nhiều khi bạn quên xin mở một số kết nối quan trong gây khó khăn cho phát triển và triển khai. Trong trường hợp này bạn có thể sử dụng ConnectionRelay.
Ví dụ: PC của bạn có IP là 192.168.1.68, kết nối được tới máy chủ ứng dụng App Server có địa chỉ là 10.0.6.88 ở cổng từ 8000 đến 10000, và từ App Server này kết nối được tới máy chủ dữ liệu Oracle Server có địa chỉ 10.0.6.89 ở cổng 1521. Vì một lý do nào đó (Như quên xin kết nối chẳng hạn) máy của bạn không thể kết nối trực tiếp tới Oracle Server, trong trường hợp này bạn triển khai ConnectionRelay trên App Server và bạn sửa thông số relay.sessions trong tệp "etc/app.properties" như sau:
relay.sessions = oracle-relay:8888:10.0.6.89:1521
Bây giờ, PC của bạn có thể truy cập tới cơ sở dữ liệu thông qua kết nối tới App Server (10.0.6.88) ở cổng 8888.
Đây là trường hợp phổ biến hay sử dụng, bạn mở rộng cho các trường hợp tương tự.
Trường hợp 2: Kết nối từ Server tới Mail Server thông qua máy Client
Bây giờ bạn gặp trường hợp, App Server của bạn không kết nối được ra Internet vì lý do bảo mật, trong khi đó ứng dụng của bạn có tính năng gửi email mà muốn truy cập tới Mail Server (smtp.gmail.com) phải có kết nối ra Internet. Trong trường hợp này nếu App Server có kết nối tới máy PC (192.168.1.68) của bạn ở port 8888 và máy PC của bạn có kết nối Internet thì bạn thực hiện như sau:
- B1: Trên máy PC của bạn triển khai ConnectionRelay với cấu hình như sau:
relay.sessions = smtp-relay:8888:smtp.gmail.com:465 - B2: Trên App Server, sửa lại cấu hình kết nối tới Mail Server thay vì smtp.gmail.com ở cổng 465 thì đổi thành 192.168.1.68 ở cổng 8888.
Ngoài ra, còn nhiều trường hợp khác bạn có thể áp dụng.
Mô tả mã nguồn của ConnectionRelay
Mã nguồn của ConnectionRelay rất đơn giản, chủ yếu là lập trình Socket để gửi nhận gói tin. Ngoài ra ứng dụng còn sử dụng thêm thư viện Log4J để ghi log. Chi tiết về Log4J, mọi người có thể xem thêm tại địa chỉ: Sử dụng Log4j để ghi log trong lập trình Java
Hai ảnh dưới mô tả các tệp mã nguồn và mô hình lớp (Class Diagram) của ứng dụng:
Trong đó:
- Start: Lớp này là điểm vào bắt đầu ứng dụng.
- Stop: Lớp này để giải phóng tài nguyên và dừng ứng dụng. Lớp Start và Stop sinh ra mục đích để giúp dễ dàng tích hợp với Java Service Wrapper. Chi tiết xem tại địa chỉ: Sử dụng Java Service Wrapper để chạy ứng dụng dưới dạng service
- Config: Lớp này đọc thông tin RelaySession từ tệp "../etc/app.properties".
- RelayInfo: Chứa thông tin một RelaySession.
- Bouncing: Lớp quản lý một luồng kết nối trong một RelaySession, lớp này là một Thread. Lớp này làm nhiệm vụ nhận bản tin từ Client và chuyển tiếp bản tin sang Server, đồng thời nhận bản tin phản hồi từ Server để trả lại cho Client.
- Relay: Quản lý một RelaySession, lớp này là một Thread. Chương trình chạy, Relay sẽ mở SocketServer và lắng ghi ở port tương ứng trong RelayInfo. Mỗi khi có 1 Client kết nối đến, Relay sẽ khởi tạo luồng đầy đủ A <-> ConnectionRelay <-> B thông qua đối tượng Bouncing. Một RelaySession có thể có nhiều luồng kết nối đến, vì thế một đối tượng Relay sẽ có nhiều đối tượng Bouncing.
- RelayManager: Lớp chính quản lý tất cả các RelaySession, mỗi RelaySession được quản lý bởi một đối tượng lớp Relay. Lớp này khi khỏi tạo sẽ đọc tệp cấu hình thông qua lớp Config để lấy thông tin tất cả các RelaySession, sau đó khởi tạo các đối tượng Relay tương ứng với mỗi RelaySession. Khi hàm start() được gọi thì tất các đối tượng Relay được chạy để chờ kết nối từ Client.
Mã nguồn của ConnectionRelay bạn có thể tải tại địa chỉ: File:ConnectionRelay-Sources.zip