Ruby 简明教程
Ruby - Socket Programming
Ruby 提供了两个级别的网络服务访问权限。在低级别,您可以访问底层操作系统中的基本套接字支持,这使您可以为面向连接和无连接协议实现客户端和服务器。
Ruby provides two levels of access to network services. At a low level, you can access the basic socket support in the underlying operating system, which allows you to implement clients and servers for both connection-oriented and connectionless protocols.
Ruby 还具有提供对特定应用程序级网络协议(例如 FTP、HTTP 等)的高级访问权限的库。
Ruby also has libraries that provide higher-level access to specific application-level network protocols, such as FTP, HTTP, and so on.
本章将帮助您了解网络中最著名的概念 - 套接字编程。
This chapter gives you an understanding on most famous concept in Networking − Socket Programming.
What are Sockets?
套接字是双向通信通道的端点。套接字可以在进程内进行通信,也可以在同一电脑上的进程之间或不同区域中的进程之间进行通信。
Sockets are the endpoints of a bidirectional communications channel. Sockets may communicate within a process, between processes on the same machine, or between processes on different continents.
套接字可以通过多种不同的信道类型进行实现:Unix 域套接字、TCP、UDP 等。套接字提供用于处理常见传输的特定类,以及用于处理其余部分的通用接口。
Sockets may be implemented over a number of different channel types: Unix domain sockets, TCP, UDP, and so on. The socket provides specific classes for handling the common transports as well as a generic interface for handling the rest.
套接字具有自己的词汇:
Sockets have their own vocabulary −
Sr.No. |
Term & Description |
1 |
domain The family of protocols that will be used as the transport mechanism. These values are constants such as PF_INET, PF_UNIX, PF_X25, and so on. |
2 |
type The type of communications between the two endpoints, typically SOCK_STREAM for connection-oriented protocols and SOCK_DGRAM for connectionless protocols. |
3 |
protocol Typically zero, this may be used to identify a variant of a protocol within a domain and type. |
4 |
hostname The identifier of a network interface − A string, which can be a host name, a dotted-quad address, or an IPV6 address in colon (and possibly dot) notation A string "<broadcast>", which specifies an INADDR_BROADCAST address. A zero-length string, which specifies INADDR_ANY, or An Integer, interpreted as a binary address in host byte order. |
5 |
port Each server listens for clients calling on one or more ports. A port may be a Fixnum port number, a string containing a port number, or the name of a service. |
A Simple Client
这里我们将编写一个非常简单的客户端程序,它将打开到给定端口和给定主机的连接。Ruby 类 TCPSocket 提供 open 函数来打开这样的套接字。
Here we will write a very simple client program, which will open a connection to a given port and given host. Ruby class TCPSocket provides open function to open such a socket.
TCPSocket.open(hosname, port ) 在端口上向 hostname 打开一个 TCP 连接。
The TCPSocket.open(hosname, port ) opens a TCP connection to hostname on the port.
一旦您打开了一个套接字,就可以像任何 IO 对象一样从中读取。完成后,请记住关闭它,就像您关闭文件一样。
Once you have a socket open, you can read from it like any IO object. When done, remember to close it, as you would close a file.
以下代码是一个非常简单的客户端,它连接到给定的主机和端口,从套接字读取任何可用数据,然后退出 −
The following code is a very simple client that connects to a given host and port, reads any available data from the socket, and then exits −
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
A Simple Server
要编写 Internet 服务器,我们使用 TCPServer 类。TCPServer 对象是 TCPSocket 对象的工厂。
To write Internet servers, we use the TCPServer class. A TCPServer object is a factory for TCPSocket objects.
现在,调用 TCPServer.open(hostname, port 函数来指定服务的端口,并创建一个 TCPServer 对象。
Now call TCPServer.open(hostname, port function to specify a port for your service and create a TCPServer object.
接下来,调用返回的 TCPServer 对象的 accept 方法。此方法会一直等到客户端连接至您指定的端口,然后返回一个 TCPSocket 对象,该对象表示与该客户端的连接。
Next, call the accept method of the returned TCPServer object. This method waits until a client connects to the port you specified, and then returns a TCPSocket object that represents the connection to that client.
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
}
现在,在后台运行此服务器,然后运行上述客户端查看结果。
Now, run this server in background and then run the above client to see the result.
Multi-Client TCP Servers
互联网上的大多数服务器都设计为一次处理大量客户端。
Most servers on the Internet are designed to deal with large numbers of clients at any one time.
Ruby 的 Thread 类简单创建多线程序。该程序可以接受请求,并立即创建一个新的执行线程来处理该连接,同时允许主程序等待更多连接−
Ruby’s Thread class makes it easy to create a multithreaded server.one that accepts requests and immediately creates a new thread of execution to process the connection while allowing the main program to await more connections −
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
}
在此示例中,您有一个永久循环,当 server.accept 响应时,会创建一个新线程,并立即启动它来处理刚刚接受的连接,方法是用连接对象传递到该线程中。然而,主程序会立即循环返回等待新连接。
In this example, you have a permanent loop, and when server.accept responds, a new thread is created and started immediately to handle the connection that has just been accepted, using the connection object passed into the thread. However, the main program immediately loops back and awaits new connections.
按照此方式使用 Ruby 线程意味着该代码是可移植的,并且可以在 Linux、OS X 和 Windows 上以相同方式运行。
Using Ruby threads in this way means the code is portable and will run in the same way on Linux, OS X, and Windows.
A Tiny Web Browser
我们可以使用 socket 库来实现任何因特网协议。例如,下面是一个获取网页内容的代码−
We can use the socket library to implement any Internet protocol. Here, for example, is a code to fetch the content of a web page −
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
要实现类似的 Web 客户端,您可以使用预先构建的库(例如 Net::HTTP )来使用 HTTP。下方的代码的作用等同于之前的代码−
To implement the similar web client, you can use a pre-built library like Net::HTTP for working with HTTP. Here is the code that does the equivalent of the previous code −
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
请查看类似的库以配合使用 FTP、SMTP、POP 和 IMAP 协议。
Please check similar libraries to work with FTP, SMTP, POP, and IMAP protocols.
Further Readings
我们为您提供了有关套接字编程的快速入门指导。这是一个大课题,因此推荐您查看 Ruby Socket Library and Class Methods 以查找更多详细信息。
We have given you a quick start on Socket Programming. It is a big subject, so it is recommended that you go through Ruby Socket Library and Class Methods to find more details.