Working with TCP Sockets 読書メモ 目次
スレッドごとの接続
スレッドとプロセス
- スレッドの方が生成コストが低い
- スレッドはメモリを共有するので、複数のスレッドで共有されるデータの取り扱いに注意が必要
- (MRIでは)スレッドはプロセスごとなので、同一の処理系の中で動く
- (MRIでは)プロセスだけが並行性(concurrency)をもっている
実装
require 'socket'
require 'thread'
require_relative 'command_handler'
module FTP
Connection = Struct.new(:clinet) do
CRLF = "\r\n"
def gets
client.gets(CRLF)
end
def respond(message)
client.write(message)
client.write(CRLF)
end
def close
client.close
end
end
class ThreadPerConnection
def initialize(port = 21)
@control_socket = TCPServer.new(port)
trap(:INT) { exit }
end
def run
Thread.abort_on_exception = true
loop do
conn = Connection.new(@control_socket.accept)
Thread.new do
conn.respond "220 OHAI"
handler = FTP::CommandHandler.new(conn)
loop do
request = conn.gets
if request
conn.respond handler.handle(request)
else
conn.close
break
end
end
end
end
end
end
end
server = FTP::ThreadPerConnection.new(4481)
server.run
- 各クライアントのコネクションを別のインスタンスにしている点に注意
- それぞれのスレッドが1つずつコネクションを処理するよう設計すべき(ベストプラクティス)
考察
- 利点:プロセスごとの接続よりもパフォーマンスが良い
- 欠点:(処理によっては)GILによるロックが発生しうる、スレッド数の上限が無い
コメントをどうぞ