Ruby - Lập trình Socket
Ruby cung cấp hai cấp độ truy cập vào các dịch vụ mạng. Ở cấp độ thấp, bạn có thể truy cập hỗ trợ socket cơ bản trong hệ điều hành cơ bản, cho phép bạn triển khai các máy khách và máy chủ cho cả giao thức hướng kết nối và không kết nối.
Ruby cũng có các thư viện cung cấp quyền truy cập cấp cao hơn vào các giao thức mạng cấp ứng dụng cụ thể, chẳng hạn như FTP, HTTP, v.v.
Chương này cung cấp cho bạn sự hiểu biết về khái niệm nổi tiếng nhất trong Mạng - Lập trình Socket.
Sockets là gì?
Các ổ cắm là các điểm cuối của một kênh truyền thông hai chiều. Sockets có thể giao tiếp trong một quy trình, giữa các quy trình trên cùng một máy hoặc giữa các quy trình trên các lục địa khác nhau.
Sockets có thể được triển khai trên một số kiểu kênh khác nhau: socket miền Unix, TCP, UDP, v.v. Các ổ cắm cung cấp các lớp cụ thể để xử lý các tàu vận tải thông thường cũng như một giao diện chung để xử lý phần còn lại.
Sockets có từ vựng riêng -
Sr.No. | Thuật ngữ & Mô tả |
---|---|
1 | domain Họ các giao thức sẽ được sử dụng làm cơ chế vận chuyển. Các giá trị này là các hằng số như PF_INET, PF_UNIX, PF_X25, v.v. |
2 | type Loại giao tiếp giữa hai điểm cuối, thường là SOCK_STREAM cho các giao thức hướng kết nối và SOCK_DGRAM cho các giao thức không kết nối. |
3 | protocol Thông thường, giá trị này có thể được sử dụng để xác định một biến thể của giao thức trong một miền và loại. |
4 | hostname Định danh của giao diện mạng - Một chuỗi, có thể là tên máy chủ, địa chỉ có dấu chấm tứ hoặc địa chỉ IPV6 trong ký hiệu dấu hai chấm (và có thể là dấu chấm) Chuỗi "<broadcast>", chỉ định địa chỉ INADDR_BROADCAST. Một chuỗi có độ dài bằng 0, chỉ định INADDR_ANY hoặc Số nguyên, được hiểu là địa chỉ nhị phân theo thứ tự byte máy chủ. |
5 | port Mỗi máy chủ lắng nghe các máy khách gọi trên một hoặc nhiều cổng. Một cổng có thể là số cổng Fixnum, một chuỗi chứa số cổng hoặc tên của một dịch vụ. |
Một khách hàng đơn giản
Ở đây chúng ta sẽ viết một chương trình khách rất đơn giản, chương trình này sẽ mở một kết nối đến một cổng nhất định và máy chủ nhất định. Lớp RubyTCPSocketcung cấp chức năng mở để mở một ổ cắm như vậy.
Các TCPSocket.open(hosname, port )mở kết nối TCP tới tên máy chủ trên cổng .
Khi bạn đã mở một ổ cắm, bạn có thể đọc từ đó giống như bất kỳ đối tượng IO nào. Khi hoàn tất, hãy nhớ đóng nó, vì bạn sẽ đóng một tệp.
Đoạn mã sau là một ứng dụng khách rất đơn giản kết nối với một máy chủ và cổng nhất định, đọc bất kỳ dữ liệu nào có sẵn từ ổ cắm, sau đó thoát ra -
require 'socket' # Sockets are in standard library
hostname = 'localhost'
port = 2000
s = TCPSocket.open(hostname, port)
while line = s.gets # Read lines from the socket
puts line.chop # And print with platform line terminator
end
s.close # Close the socket when done
Một máy chủ đơn giản
Để viết máy chủ Internet, chúng tôi sử dụng TCPServerlớp học. Đối tượng TCPServer là một nhà máy cho các đối tượng TCPSocket.
Gọi ngay TCPServer.open(hostname, portchức năng chỉ định một cổng cho dịch vụ của bạn và tạoTCPServer vật.
Tiếp theo, gọi phương thức chấp nhận của đối tượng TCPServer được trả về. Phương thức này đợi cho đến khi một máy khách kết nối với cổng bạn đã chỉ định, rồi trả về một đối tượng TCPSocket đại diện cho kết nối với máy khách đó.
require 'socket' # Get sockets from stdlib
server = TCPServer.open(2000) # Socket to listen on port 2000
loop { # Servers run forever
client = server.accept # Wait for a client to connect
client.puts(Time.now.ctime) # Send the time to the client
client.puts "Closing the connection. Bye!"
client.close # Disconnect from the client
}
Bây giờ, chạy máy chủ này ở chế độ nền và sau đó chạy ứng dụng khách trên để xem kết quả.
Máy chủ TCP đa máy khách
Hầu hết các máy chủ trên Internet được thiết kế để xử lý số lượng lớn khách hàng cùng một lúc.
Lớp Thread của Ruby giúp dễ dàng tạo một máy chủ đa luồng chấp nhận các yêu cầu và ngay lập tức tạo một luồng thực thi mới để xử lý kết nối trong khi vẫn cho phép chương trình chính chờ đợi nhiều kết nối hơn -
require 'socket' # Get sockets from stdlib
server = TCPServer.open(2000) # Socket to listen on port 2000
loop { # Servers run forever
Thread.start(server.accept) do |client|
client.puts(Time.now.ctime) # Send the time to the client
client.puts "Closing the connection. Bye!"
client.close # Disconnect from the client
end
}
Trong ví dụ này, bạn có một vòng lặp vĩnh viễn và khi server.accept phản hồi, một luồng mới sẽ được tạo và bắt đầu ngay lập tức để xử lý kết nối vừa được chấp nhận, bằng cách sử dụng đối tượng kết nối được truyền vào luồng. Tuy nhiên, chương trình chính ngay lập tức lặp lại và chờ các kết nối mới.
Sử dụng các chuỗi Ruby theo cách này có nghĩa là mã có thể di động và sẽ chạy theo cùng một cách trên Linux, OS X và Windows.
Trình duyệt web nhỏ
Chúng ta có thể sử dụng thư viện socket để triển khai bất kỳ giao thức Internet nào. Ví dụ ở đây là một đoạn mã để tìm nạp nội dung của một trang web -
require 'socket'
host = 'www.tutorialspoint.com' # The web server
port = 80 # Default HTTP port
path = "/index.htm" # The file we want
# This is the HTTP request we send to fetch a file
request = "GET #{path} HTTP/1.0\r\n\r\n"
socket = TCPSocket.open(host,port) # Connect to server
socket.print(request) # Send request
response = socket.read # Read complete response
# Split response at first blank line into headers and body
headers,body = response.split("\r\n\r\n", 2)
print body # And display it
Để triển khai ứng dụng khách web tương tự, bạn có thể sử dụng thư viện được tạo sẵn như Net::HTTPđể làm việc với HTTP. Đây là mã tương đương với mã trước đó -
require 'net/http' # The library we need
host = 'www.tutorialspoint.com' # The web server
path = '/index.htm' # The file we want
http = Net::HTTP.new(host) # Create a connection
headers, body = http.get(path) # Request the file
if headers.code == "200" # Check the status code
print body
else
puts "#{headers.code} #{headers.message}"
end
Vui lòng kiểm tra các thư viện tương tự để hoạt động với các giao thức FTP, SMTP, POP và IMAP.
Đọc thêm
Chúng tôi đã cung cấp cho bạn một khởi đầu nhanh về Lập trình Socket. Đây là một chủ đề lớn, vì vậy bạn nên đi qua Thư viện Ruby Socket và Phương thức lớp để tìm thêm chi tiết.