EventManager を使用して Ruby でチャット サーバーを構築しようとしています。言うまでもなく、私は Ruby に慣れていないので、現在発生しているエラーに少し戸惑っています。それが何を意味するのか見当がつかず、検索しても価値のあるものは何も返されないからです。ロジスティクスの一部を次に示します。
(私は LOGIN と REGISTER しか実装していないので、それらだけを含めます..) user can enter- REGISTER username password - register user LOGIN username password - logins user
ユーザーが送信したデータの文字列を取り込んで、それを msg という配列に分割し、msg[0] に基づいてデータを処理します (REGISTER、LOGIN などのコマンドとして)。
これが私のコードで、すべてが単一のファイルchatserver.rbに含まれています(説明が続きます):
require 'rubygems'
require 'eventmachine'
class Server
attr_accessor :clients, :channels, :userCreds, :userChannels
def initialize
@clients = [] #list of clients connected e.g. [192.168.1.2, 192.168.1.3]
@users = {} #list of users 'logged in' e.g. [tom, sam, jerry]
@channels = [] #list of channels e.g. [a, b, c]
@userCreds = {} #user credentials hash e.g. { tom: password1, sam: password2, etc }
@userChanels = {} #users and their channels e.g. { tom: a, sam: a, jerry: b }
end
def start
@signature = EventMachine.start_server("127.0.0.1", 3200, Client) do |con|
con.server = self
end
end
def stop
EventMachine.stop_server(@signature)
unless wait_for_connections_and_stop
EventMachine.add_periodic.timer(1) { wait_for_connections_and_stop }
end
end
# Does the username already exist?
def has_username?(name)
@userCreds.has_key?(name)
end
# Is the user already logged in?
def logged_in?(name)
if @users[name] == 1
true
else
false
end
end
# Did the user enter the correct pwd?
def correct_pass?(pass)
if @userCreds[name] == pass
true
else
false
end
end
private
def wait_for_connections_and_stop
if @clients.empty?
EventMachine.stop
true
else
puts "Waiting for #{@clients.size} client(s) to stop"
false
end
end
end
class Connection < EventMachine::Connection
attr_accessor :server, :name, :msg
def initialize
@name = nil
@msg = []
end
# First thing the user sees when they connect to the server.
def post_init
send_data("Welcome to the lobby.\nRegister or Login with REGISTER/LOGIN username password\nOr try HELP if you get stuck!")
end
# Start parsing incoming data
def receive_data(data)
data.strip!
msg = data.split("") #split data by spaces and throw it in array msg[]
if data.empty? #the user entered nothing?
send_data("You didn't type anything! Try HELP.")
return
elsif msg[0] == "REGISTER"
handle_register(msg) #send msg to handle_register method
else
hanlde_login(msg) #send msg to handle_login method
end
end
def unbind
@server.clients.each { |client| client.send_data("#{@name} has just left") }
puts("#{@name} has just left")
@server.clients.delete(self)
end
private
def handle_register(msg)
if @server.has_username? msg[1] #user trying to register with a name that already exists?
send_data("That username is already taken! Choose another or login.")
return
else
@name = msg[1] #set name to username
@userCreds[name] = msg[2] #add username and password to user credentials hash
send_data("OK") #send user OK message
end
end
end
EventMachine::run do
s = Server.new
s.start #start server
puts "Server listening"
end
ふう、まあ、それはほんの始まりにすぎないので、それほど複雑ではありません。私はRubyが初めてなので、変数を宣言していないか、スコープを正しく使用していないだけだと感じています。エラー出力は次のとおりです。
chatserver.rb:16:in
start': uninitialized constant Server::Client (NameError) from chatserver.rb:110:in
block in ' from /Users/meth/.rvm/gems/ruby-1.9.3-p392@rails3tutorial2ndEd/gems/eventmachine-1.0.3/lib/eventmachine.rb:187:incall' from /Users/meth/.rvm/gems/ruby-1.9.3-p392@rails3tutorial2ndEd/gems/eventmachine-1.0.3/lib/eventmachine.rb:187:in
run_machine' from /Users/meth/.rvm/gems/ruby-1.9.3-p392@rails3tutorial2ndEd/gems/eventmachine-1.0.3/lib/eventmachine.rb:187:inrun' from chatserver.rb:108:in
<\main>'
その最後の行の main のスラッシュは無視してください。108 行目は最後の関数です。EventMachine::run do などです。
十分な情報を提供していない場合は、お知らせください。