Ruby Socket 编程
-
Socket 编程
Ruby提供了对网络服务的两个访问级别。在较低的级别上,您可以访问底层操作系统中的基本Socket支持,从而可以为面向连接和无连接的协议实现客户端和服务器。Ruby还具有提供对特定应用程序级网络协议(例如FTP,HTTP等)的更高级别访问的库。-本章将使您对网络-Socket编程中最著名的概念有所了解。 -
什么是 Socket(套接字)
套接字是双向通信通道的端点。套接字可以在一个进程内,同一台机器上的进程之间或不同机器上的进程之间进行通信。套接字可以通过许多不同的通道类型实现:Unix域套接字,TCP,UDP等。套接字提供特定的类来处理常见的传输以及用于处理其余的通用接口。套接字有自己的词汇表-控件 说明 domain 用作传输机制的协议系列。 这些值是常量,例如PF_INET,PF_UNIX,PF_X25等。 type 两个端点之间的通信类型,通常是面向连接协议的SOCK_STREAM和无连接协议的SOCK_DGRAM。 protocol 通常为零,可用于标识域和类型内协议的变体。 hostname 网络接口的标识符- - 字符串,可以是主机名,点分四进制地址或IPV6地址(以冒号(可能是点)表示)
- 字符串“<broadcast>”,它指定INADDR_BROADCAST地址。
- 零长度的字符串,它指定INADDR_ANY,或者
- 一个整数,按主机字节顺序解释为二进制地址。
port 每个服务器侦听在一个或多个端口上调用的客户端。 端口可以是Fixnum端口号,包含端口号的字符串或服务名称。 -
一个简单的服务端
要编写Internet服务器,我们使用TCPServer类。TCPServer对象是TCPSocket对象的工厂。现在调用TCPServer.open(hostname,port函数)为您的服务指定一个端口并创建一个TCPServer对象。接下来,调用返回的TCPServer对象的accept方法。此方法一直等到客户端连接到您指定的端口,然后返回一个表示与该客户端的连接的TCPSocket对象。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 }
-
一个简单的客户端
在这里,我们将编写一个非常简单的客户端程序,该程序将打开到给定端口和给定主机的连接。Ruby类TCPSocket提供了打开函数来打开这样的套接字。TCPSocket.open(hosname,端口)打开一个TCP连接到主机上的端口。打开套接字后,就可以像读取任何IO对象一样从中读取套接字。完成后,记得关闭它,就像关闭文件一样。以下代码是一个非常简单的客户端,该客户端连接到给定的主机和端口,从套接字读取任何可用数据,然后退出-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 # 并使用平台行终止符进行打印 end s.close # Close the socket when done
现在,在后台运行此服务器,然后重新打开一个终端运行上面的客户端以查看结果。如下所示: -
多客户端TCP服务器
Internet上的大多数服务器都设计为可以同时处理大量客户端。Ruby的Thread类使创建多线程服务器变得很容易。一个服务器接受请求并立即创建一个新的执行线程来处理连接,同时允许主程序等待更多连接-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响应时,将使用传递到线程中的连接对象来创建并立即启动一个新线程,以处理刚刚接受的连接。但是,主程序立即循环并等待新的连接。以这种方式使用Ruby线程意味着代码是可移植的,并且将在Linux,OS X和Windows上以相同的方式运行。 -
微型Web浏览器
我们可以使用套接字库来实现任何Internet协议。例如,这是获取网页内容的代码-require 'socket' host = 'www.cainiaoya.com' # The web server port = 80 # Default HTTP port path = "/index.php" # 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。这是与先前代码等效的代码-require 'net/http' # The library we need host = 'www.cainiaoya.com' # The web server path = '/index.php' # 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协议。Socket 编程这是一个很大的主题,因此建议您查阅Ruby Socket库和类方法以找到更多详细信息。