LoginSignup
1
0

More than 5 years have passed since last update.

RubyでTCP通信 on windows

Posted at

RubyでTCPサーバー/クライアントを作ってみる

サンプルをコピペしただけだと上手く動かないor微妙な点がいくつかあったので備忘録です。

サーバー

# server
require 'socket'
# 3030番ポートを開く
gs = TCPServer.open(nil, 3030)
socks = [gs]

puts "server is on #{gs.addr}"

loop {
  nsock = select(socks)
  next unless nsock[0]
  nsock[0].each do |s|
    if s == gs
      ns = s.accept
      socks.unshift ns
      puts "#{ns} is accept"
    else
      if s.eof?
        puts "#{s} is gone."
        s.close
        socks.delete(s)
      else
        msg = s.readpartial(4 * 1024)
        p msg
      end
      break
    end
  end
}

クライアント

# client
require 'socket'

s = TCPSocket.open("localhost", 3030)
while msg = gets
  puts "write #{msg}"
  s.write msg
end

仕様を変更した点

  • サーバー側の通信読み込み部分をs.getsからs.readpartialへ変更
    文字列ならばいいのかもしれないが、今後バイト列を書き込み/読み込みを考えるとgetsではダメな可能性がある。
  • サーバー側のaccept時にsocks.pushではなくsocks.unshiftを用いTCPServerソケットの優先度を下げた
  • select後TCPSocketに対して通信を行ったあとはbreakで再度selectへ移行するようにした。
    上2つはwindows特有のバグなのかは分かりませんが、readpartial時に指定した以上の長さの通信がある場合
    次回のselectで、どういうわけかTCPServerが読み込み待ちになるバグへの対処です。

反省

s.nreadでブロックなしに読み取れるバイト数が取れるのでコレを使うといいかもしれない。
但し、タイミング次第でやはりselectのバグ?を踏むと思われるので待ち行列の優先度等については考慮する必要がある。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0