読者です 読者をやめる 読者になる 読者になる

タイムアウトを発生させるためにやったあれやこれや

urllib2 のタイムアウトの調査で、タイムアウトを起こすためにいくつかコードを書きました。

大したことはやってないのですが、書いては捨て書いては捨てしてたので、参考のためにコードを貼り付けまくっときます。
ださー、と言って笑ってやってください。


最初に書いたのは mod_ruby を使った Ruby CGI です。

puts "Content-Type: text/plain"
puts ""

sleep 10

puts "hello world"

最初このコードで実験していて、URLError が発生することを確認してました。
urllib2.py を読みつつ HTTP ヘッダだけ送ろうと試行錯誤してみたのですが、
いくら STDOUT.flush しても最後の行が処理されるまでクライアントには渡っていかなかったので、
さっさとギブアップして次へ。

次は wsgi を使ったらいけるんじゃないかと思いついて wsgi.simple_server に飛びついてみました。

import time
from wsgiref.simple_server import make_server

def app(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/plain')])

    time.sleep(10)
    return ["hello world"]

httpd = make_server('', 8081, app)
print "Serving on port 8081..."
httpd.serve_forever()

…が、こちらも HTTP ヘッダだけ送信する方法が分からなかったので、即効(3分ぐらい)で捨て。

最後は生 socket で書くことにしました。

require 'socket'

serv = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
sockaddr = Socket.sockaddr_in(8081, "0.0.0.0")
serv.bind(sockaddr)
serv.listen(5)
while true
  sock, sockaddr = serv.accept
  begin
    sock.write("Content-Type: text/plain\n\n")
    sock.flush

    sleep 10

    sock.write("hello world\n")
    sock.flush
    sock.close
  rescue
  end
end

これだとうまくいくので、sleep の位置を動かしながらどこでどういうエラーが出るのか確かめてました。


さて、mod_rubywsgi.simple_server でストリーム送信する方法はあるのでしょうか。
いずれ調べないといけないと思いつつ、今日はこの程度にしておいてやるか、と言って去っていくのでした。