查看: 3096|回复: 5

[胡扯] 写了一个用TCP Socket在控制台聊天的东西……

[复制链接]
梦石
0
星屑
1944
在线时间
404 小时
注册时间
2015-8-30
回帖
322
发表于 2018-8-29 20:46:35 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有账号?注册会员

×
本帖最后由 有丘直方 于 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]
服务端效果 QQ截图20180829203429.png QQ截图20180829203807.png QQ截图20180829204436.png
客户端效果 QQ截图20180829203634.png QQ截图20180829204247.png QQ截图20180829204336.png
小仙女一枚~

老黄鸡

梦石
4
星屑
45700
在线时间
7948 小时
注册时间
2009-7-6
回帖
13338

MZ评测员RM创作大赛01组委会开拓者贵宾

发表于 2018-8-30 08:34:31 | 显示全部楼层
require('socket')

我以为RGSS可用的

点评

工作量大,时间不多  发表于 2018-8-30 19:44
所以为什么黄鸡不把rgd的ruby换个非阉割版啊  发表于 2018-8-30 17:40
我记得有大佬用Win32API做了个Socket可以在RGSS里面用  发表于 2018-8-30 09:42
RGDirect - DirectX驱动的RGSS,点我了解.
(排满,暂停)RM全系列成套系统定制请联系QQ1213237796
不接受对其他插件维护的委托
回复

使用道具 举报

梦石
0
星屑
1803
在线时间
133 小时
注册时间
2013-10-6
回帖
181
发表于 2018-9-3 21:30:26 | 显示全部楼层
foobar.png
我想起来以前用C#做过类似的东西,协议看起来像HTTP/1.X
←你看到一只经常潜水的萌新。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部