ruby - Ruby unix 套接字客户端和服务器示例
问题描述
我发现了很多关于使用 unix 套接字运行服务器的一般信息,但我不能完全让它工作。这就是我想做的一切。服务器创建一个 unix 套接字,然后监听它。当请求进来时,它会处理请求,然后发出响应。现在,何时请求或发生什么处理都无关紧要。“你好世界”现在很好。
这是我现在拥有的服务器和客户端脚本。据我所知,两者都不起作用。
服务器:
#!/usr/bin/ruby -w
require 'socket'
server = UNIXServer.new('/tmp/socket-simple')
socket = server.accept
socket.write 'Hello world'
socket.close
server.close
客户端:
#!/usr/bin/ruby -w
require 'net_http_unix'
request = Net::HTTP::Get.new('whatever')
client = NetX::HTTPUnix.new('unix://' + '/tmp/socket-simple')
response = client.request(request)
puts response.body
我期望发生的是客户端发送那个简单的请求,返回“Hello world”,并显示那个响应。这就是实际发生的事情。
客户端脚本输出此错误:
Traceback (most recent call last):
16: from ./socket-client.rb:8:in `<main>'
15: from /usr/lib/ruby/2.5.0/net/http.rb:1458:in `request'
14: from /usr/lib/ruby/2.5.0/net/http.rb:910:in `start'
13: from /usr/lib/ruby/2.5.0/net/http.rb:1460:in `block in request'
12: from /usr/lib/ruby/2.5.0/net/http.rb:1467:in `request'
11: from /usr/lib/ruby/2.5.0/net/http.rb:1493:in `transport_request'
10: from /usr/lib/ruby/2.5.0/net/http.rb:1536:in `begin_transport'
9: from /var/lib/gems/2.5.0/gems/net_http_unix-0.2.2/lib/net_x/http_unix.rb:24:in `connect'
8: from /var/lib/gems/2.5.0/gems/net_http_unix-0.2.2/lib/net_x/http_unix.rb:35:in `connect_unix'
7: from /usr/lib/ruby/2.5.0/timeout.rb:108:in `timeout'
6: from /usr/lib/ruby/2.5.0/timeout.rb:33:in `catch'
5: from /usr/lib/ruby/2.5.0/timeout.rb:33:in `catch'
4: from /usr/lib/ruby/2.5.0/timeout.rb:33:in `block in catch'
3: from /usr/lib/ruby/2.5.0/timeout.rb:93:in `block in timeout'
2: from /var/lib/gems/2.5.0/gems/net_http_unix-0.2.2/lib/net_x/http_unix.rb:35:in `block in connect_unix'
1: from /var/lib/gems/2.5.0/gems/net_http_unix-0.2.2/lib/net_x/http_unix.rb:35:in `open'
/var/lib/gems/2.5.0/gems/net_http_unix-0.2.2/lib/net_x/http_unix.rb:35:in `initialize': Connection refused - connect(2) for /tmp/socket-simple (Errno::ECONNREFUSED)
服务器似乎工作正常,除了它使 unix 套接字文件保持打开状态。我可以通过删除 /tmp/socket-simple 来终止该套接字。
所以我在这里很迷茫。任何人都可以提供我想要的客户端和服务器脚本的工作示例吗?
解决方案
据我所知,两者都不起作用。
这是不正确的;你的客户很好。但是,您的服务器不是。
您的客户端代码正在尝试使用 HTTP 进行通信。您的服务器代码中没有任何内容实现 HTTP 语义。
我相信发生在您身上的是:客户端连接。服务器说“Hello world”并关闭连接,就像客户端开始发送标头一样。客户发现它正在与墙壁通话,并且由于传输标头是强制性的,因此它放弃了一个错误。
这意味着,您至少必须让客户端在关闭连接之前说出 HTTP 标头。您还必须发送 HTTP 响应标头,否则 HTTP 客户端会发现自己非常混乱。
这是适用于我的最小服务器代码:
#!/usr/bin/ruby -w
require 'socket'
begin
server = UNIXServer.new('/tmp/socket-simple')
socket = server.accept
# read the headers, at least
while socket.gets.chomp != ""
end
# send the HTTP response header
socket.puts "HTTP/1.1 200 OK"
socket.puts "Content-Type: text/plain"
socket.puts
# only now can you send a response body
socket.puts 'Hello world'
socket.close
server.close
ensure
File.unlink('/tmp/socket-simple')
end
虽然这是超级简单的,而且不是很正确(例如,它会在 POST 和许多其他细节上失败)。你可能最好使用 Rack,它已经知道如何正确地使用 HTTP。Host
如果您在其参数中提供路径,Rack 可以使用 UNIX 套接字。例如:
require 'rack'
require 'thin'
class TestApp
def call(env)
[200, {"Content-Type" => "text/plain"}, ["Hello World!"]]
end
end
app = TestApp.new
Rack::Handler.get('thin').run(app, Host: '/tmp/socket-simple')
编辑:这是使用 WEBrick 的无依赖版本。WEBrick 不直接支持 UNIX 套接字,所以我们必须阻止它尝试侦听,并插入我们自己的侦听器:
require 'webrick'
require 'socket'
begin
UNIXServer.open('/tmp/socket-simple') do |ssocket|
server = WEBrick::HTTPServer.new(DoNotListen: true)
server.listeners << ssocket
server.mount_proc '/' do |req, res|
res.set_content_type('text/plain')
res.body = "Hello, world!"
end
server.start
end
ensure
File.unlink('/tmp/socket-simple')
end
推荐阅读
- azure - Azure 传统负载均衡器 VS Azure 应用程序网关响应延迟?
- python - 获取 numpy 数组切片的索引
- python-3.x - 在 Python 中打印两个计数器之间的差异结果
- php - 使用 Laravel 模型保存多级数组
- javascript - 从父组件传递到子组件的功能不起作用
- emu8086 - 如何将伪代码更改为 EMU8086 代码?可以帮助我吗?
- python - 更改 IF 循环内的变量值
- amazon-web-services - AWS Certificate Manager,无法获取子域的 https
- php - 在 php 中设置首字母大写,但 ucfirst(strtolower('string')) 不起作用
- python - TypeError: ufunc 'add' 不包含签名匹配类型 dtype('
我是 Python 用户的初学者。当我尝试在下面编写代码时发生错误
import numpy as np np.array(['a', 'b', 'c']) + np.array(['d' ,'e', 'f'])
Type