【问题标题】:communication between two clients in RubyRuby 中两个客户端之间的通信
【发布时间】:2017-02-21 23:26:20
【问题描述】:

我正在尝试创建一个 Ruby 程序,该程序将在两个客户端之间发送消息,服务器位于中间。例如,客户端 A 连接到服务器,客户端 B 连接到相同的服务器和端口。客户 A 说“你好吗?”客户 B 说“做得好”。有点像聊天服务器。我正在考虑让服务器从客户端 A 获取消息并发送到客户端 B。到目前为止,我有这个使用证书连接的工作客户端和服务器程序。我遇到的问题是我的服务器发送回客户端 A,而我不知道如何发送到第二个连接(客户端 B)。

客户

#!/usr/bin/ruby
require "socket"
require "openssl"
require "thread"

host = ARGV[0]
port = Integer(ARGV[1])

socket = TCPSocket.new(host, port)
certificate = OpenSSL::X509::Certificate.new(File.open("server.crt"))
ssl = OpenSSL::SSL::SSLSocket.new(socket)
ssl.sync_close = true
ssl.connect
if ssl.peer_cert.to_s != certificate.to_s
  stderrr.puts "Unexpected certificate"
  exit(1)
end

# Get input through the server
Thread.new {
  begin
    while server_res = ssl.gets.chomp
      puts server_res
    end
  rescue
    $stderr.puts "Error in server response loop: " + $!
  end
}
# send out the STDIN to the server
while (client_sent = STDIN.gets.chomp)
  ssl.puts client_sent 
end

服务器

#!/usr/bin/ruby

require "socket"
require "openssl"
require "thread"

port = Integer(ARGV[0])
server = TCPServer.new(port)

sslCont = OpenSSL::SSL::SSLContext.new
sslCont.cert = OpenSSL::X509::Certificate.new(File.open("server.crt"))
sslCont.key = OpenSSL::PKey::RSA.new(File.open("server.key"))

sslServ = OpenSSL::SSL::SSLServer.new(server, sslCont)

loop {
  connection = sslServ.accept
  Thread.new {
    begin
      while (client_sent = connection.gets) do
        client_sent = client_sent.chomp
        puts "Client Sent: " + client_sent
        server_res = "Server Response: " + client_sent
        puts server_res
        connection.puts server_res
      end
    rescue
      $stderr.puts $!
    end
  }
}

【问题讨论】:

  • 证书真的是您问题的一部分吗?如果没有,请考虑从您的示例代码中删除它们。

标签: ruby sockets client-server chat


【解决方案1】:
  • 保留一系列接受的连接

    connections = []
    
  • 在有人连接或断开连接时保持最新

    connections << connection
    ...
    connections.delete(connection)
    
  • 发送时,可以发送给所有人:

    connections.each do |conn|
      conn.puts server_res
    end
    
  • 或者只是除了当前的之外的所有:

    connections.each do |conn|
      next if conn == connection
      conn.puts server_res
    end
    
  • 编辑:从 cmets 移出,因为它很重要:将 connections.delete 放入 begin...rescue...finally...end 块的 finally 子句中。这样,它会在连接因任何原因中断时执行(无论是自然地破坏while 条件,还是不自然地由于异常)。你不能做的是把它放在线程块之外,因为每个connection一被放入就会从connections中取出。

【讨论】:

  • 在 cmets 中读取任何非平凡的代码长度是痛苦的,但这似乎是我的想法。我能看到的一件事是错误的:我在 finally 子句中有 connections.delete;它当然不能在线程块之外,因为它会立即被删除。
  • 我会试试你的建议。抱歉,我一直在尝试将代码整齐地发送给您,但它不起作用,我无法删除它。
  • 没关系。将来,请尝试通过编辑您的问题而不是在 cmets 中发布任何更大的代码。
  • 所以我仍然无法让它工作。什么也没有变。 Here is my code
  • connections = [] 需要在循环之外,或者一直清空。
猜你喜欢
  • 1970-01-01
  • 2019-01-20
  • 2012-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多