| 赞 | 15 |
| VIP | |
| 好人卡 | |
| 积分 | 19 |
| 经验 | |
| 最后登录 | 2026-5-25 |
| 在线时间 | 404 小时 |
- 梦石
- 0
- 星屑
- 1944
- 在线时间
- 404 小时
- 注册时间
- 2015-8-30
- 回帖
- 322
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有账号?注册会员
×
本帖最后由 有丘直方 于 2018-8-29 20:50 编辑
闲着瞎整的玩意儿
由于我只有一台机器,服务器地址是localhost
具体看下面通用模块[pre lang="ruby" file="talk_common.rb"]# File: talk_common.rb
require('socket')
module Talk
HOST = "localhost"
PORT = 7979
ANONYM = "Someone"
CLOSE = "The server has been closed."
class << self
def init
end
def run
end
end
class TalkServer < TCPServer
JOIN = "%s joined."
LEAVE = "%s leaved."
MESSAGE = "%1$s: %2$s"
START = "The server has been started."
MESSAGE_TAG = :message
NAME_TAG = :name
LEAVE_TAG = :leave
MESSAGE_REGEXP = /^<m>(?<#{MESSAGE_TAG}>.*)<\/m>$/
NAME_REGEXP = /^<n>(?<#{NAME_TAG}>.*)<\/n>$/
LEAVE_REGEXP = /^<o>(?<#{LEAVE_TAG}>.*)<\/o>$/
attr_reader(:threads)
def initialize
super(PORT)
end
def init
@threads = []
@clients = []
push_thread(listen_accept_thread)
send_message(START)
end
def push_thread(thread)
@threads.push(thread)
end
def listen_accept_thread
Thread.new do
while client = accept
@clients.push(client)
push_thread(listen_talk_thread(client))
end
end
end
def listen_talk_thread(client)
Thread.new do
begin
while message = client.gets
args = [client, message]
client_order(*args, MESSAGE_REGEXP, MESSAGE_TAG, :client_talk)
client_order(*args, NAME_REGEXP, NAME_TAG, :make_name)
client_order(*args, LEAVE_REGEXP, LEAVE_TAG, :announce_leave)
end
rescue Errno::ECONNRESET
announce_leave(client)
Thread.exit
end
end
end
def send_message(message)
$stdout.puts(message)
each_client {|client| client.puts(message) }
end
def announce_join(client, arg = nil)
send_message(sprintf(JOIN, get_name(client)))
end
def announce_leave(client, arg = nil)
send_message(sprintf(LEAVE, get_name(client)))
end
def client_talk(client, message)
send_message(sprintf(MESSAGE, get_name(client), message))
end
def get_name(client)
client.name rescue ANONYM
end
def client_order(client, message, regexp, tag, method_name)
if content = regexp.match(message)
method(method_name).call(client, content[tag])
end
end
def make_name(client, name)
index = @clients.index(client)
client.singleton_class.send(:attr_accessor, :name)
client.name = name
announce_join(client)
@clients[index] = client
end
def each_thread(&block)
@threads.each(&block)
end
def each_client(&block)
@clients.each do |client|
begin
block.call(client)
rescue Errno::ECONNRESET
next
end
end
end
def run
init
each_thread(&:join)
end
def close
send_message(CLOSE)
each_thread(&:kill)
each_client(&:close)
super
end
end
class TalkClient < TCPSocket
INPUT_NAME = "Input your name: "
LEAVE_FORMAT = "<o>%s</o>"
MESSAGE_FORMAT = "<m>%s</m>"
NAME_FORMAT = "<n>%s</n>"
attr_reader(:name)
def initialize
super(HOST, PORT)
end
def init
@name = ANONYM
@thread1 = listen_talk_thread
@thread2 = listen_send_thread
input_name
end
def input_name
@name = @@name
puts(sprintf(NAME_FORMAT, @name))
end
def self.input_name
$stdout.print(INPUT_NAME)
@@name = $stdin.gets
@@name[@@name.size - 1] = ""
end
def listen_talk_thread
Thread.new do
begin
while message = gets
$stdout.puts(message)
end
rescue
$stdout.puts(CLOSE)
Thread.list.each(&exit)
end
end
end
def listen_send_thread
Thread.new do
begin
while message = $stdin.gets
message[message.size - 1] = ""
puts(sprintf(MESSAGE_FORMAT, message))
end
rescue
$stdout.puts(CLOSE)
Thread.list.each(&exit)
end
end
end
def close
puts(LEAVE_FORMAT)
super
end
def run
init
@thread1.join
@thread2.join
end
end
end
[/pre]服务端[pre lang="ruby" file="talk_server.rb"]# File: talk_server.rb
require('talk_common')
class << Talk
def init
@server = Talk::TalkServer.new
end
def run
init
@server.run
end
end
Talk.run
[/pre]客户端[pre lang="ruby" file="talk_client.rb"]# File: talk_client.rb
require('talk_common')
class << Talk
def init
Talk::TalkClient.input_name
@client = Talk::TalkClient.new
end
def run
init
@client.run
end
end
Talk.run
[/pre]服务端效果
客户端效果
|
|