• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

shogi-server source


Commit MetaInfo

Revision452e4e0ddfb420fbd61224bd2fe914e0276c96e0 (tree)
Time2020-10-05 00:06:13
AuthorMizar <mizar.jp@gmai...>
CommiterMizar

Log Message

tcp_keepalive

Change Summary

Incremental Difference

--- a/bin/usiToCsa.rb
+++ b/bin/usiToCsa.rb
@@ -28,6 +28,7 @@ $:.unshift(File.join(File.dirname(File.expand_path(__FILE__)), ".."))
2828 require 'shogi_server'
2929 require 'logger'
3030 require 'socket'
31+require 'timeout'
3132
3233 # Global variables
3334
@@ -103,7 +104,12 @@ def parse_command_line
103104 ["--password", GetoptLong::REQUIRED_ARGUMENT],
104105 ["--ponder", GetoptLong::NO_ARGUMENT],
105106 ["--port", GetoptLong::REQUIRED_ARGUMENT],
106- ["--floodgate", GetoptLong::NO_ARGUMENT])
107+ ["--floodgate", GetoptLong::NO_ARGUMENT],
108+ ["--ignoremultiselect", GetoptLong::NO_ARGUMENT],
109+ ["--tcpkeepalive", GetoptLong::REQUIRED_ARGUMENT],
110+ ["--tcpkeepalive-idle", GetoptLong::REQUIRED_ARGUMENT],
111+ ["--tcpkeepalive-intvl", GetoptLong::REQUIRED_ARGUMENT],
112+ ["--tcpkeepalive-cnt", GetoptLong::REQUIRED_ARGUMENT])
107113 parser.quiet = true
108114 begin
109115 parser.each_option do |name, arg|
@@ -131,6 +137,15 @@ def parse_command_line
131137 options[:port] ||= ENV["PORT"] || 4081
132138 options[:port] = options[:port].to_i
133139 options[:floodgate] ||= ENV["FLOODGATE"] || false
140+ options[:ignoremultiselect] ||= ENV["IGNORE_MULTISELECT"] || false
141+ options[:tcpkeepalive] ||= ENV["TCPKEEPALIVE"] || 0
142+ options[:tcpkeepalive] = options[:tcpkeepalive].to_i
143+ options[:tcpkeepalive_idle] ||= ENV["TCPKEEPALIVE_IDLE"] || 50
144+ options[:tcpkeepalive_idle] = options[:tcpkeepalive_idle].to_i
145+ options[:tcpkeepalive_intvl] ||= ENV["TCPKEEPALIVE_INTVL"] || 5
146+ options[:tcpkeepalive_intvl] = options[:tcpkeepalive_intvl].to_i
147+ options[:tcpkeepalive_cnt] ||= ENV["TCPKEEPALIVE_CNT"] || 9
148+ options[:tcpkeepalive_cnt] = options[:tcpkeepalive_cnt].to_i
134149
135150 return options
136151 end
@@ -466,7 +481,14 @@ class BridgeState
466481 throw "Bad state at event_engine_recv: #@state"
467482 end
468483
469- str = $server.gets
484+ str = nil
485+ begin
486+ Timeout.timeout(0.001){
487+ str = $server.gets
488+ }
489+ rescue Timeout::Error
490+ $logger.error "event_server_recv timeout"
491+ end
470492 return if str.nil? || str.strip.empty?
471493 log_server_recv str
472494
@@ -619,6 +641,30 @@ def login
619641 begin
620642 $server = TCPSocket.open($options[:host], $options[:port])
621643 $server.sync = true
644+ if $options[:tcpkeepalive] > 0 &&
645+ Socket.const_defined?(:SOL_SOCKET) &&
646+ Socket.const_defined?(:SO_KEEPALIVE) &&
647+ Socket.const_defined?(:IPPROTO_TCP)
648+ $server.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true)
649+ if Socket.const_defined?(:TCP_KEEPIDLE) &&
650+ Socket.const_defined?(:TCP_KEEPINTVL) &&
651+ Socket.const_defined?(:TCP_KEEPCNT)
652+ $server.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_KEEPIDLE, $options[:tcpkeepalive_idle])
653+ $server.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_KEEPINTVL, $options[:tcpkeepalive_intvl])
654+ $server.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_KEEPCNT, $options[:tcpkeepalive_cnt])
655+ elsif RUBY_PLATFORM.downcase =~ /mswin|mingw|cygwin|bccwin/
656+ # Windows 10 (1709 or later) ws2ipdef.h
657+ # https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-tcp-socket-options
658+ $server.setsockopt(Socket::IPPROTO_TCP, 3, $options[:tcpkeepalive_idle])
659+ $server.setsockopt(Socket::IPPROTO_TCP, 17, $options[:tcpkeepalive_intvl])
660+ $server.setsockopt(Socket::IPPROTO_TCP, 16, $options[:tcpkeepalive_cnt])
661+ elsif RUBY_PLATFORM.downcase =~ /darwin/
662+ # macOS 10.12.6 (Sierra) /usr/include/netinet/tcp.h
663+ $server.setsockopt(Socket::IPPROTO_TCP, 0x10, $options[:tcpkeepalive_idle])
664+ $server.setsockopt(Socket::IPPROTO_TCP, 0x101, $options[:tcpkeepalive_intvl])
665+ $server.setsockopt(Socket::IPPROTO_TCP, 0x102, $options[:tcpkeepalive_cnt])
666+ end
667+ end
622668 rescue
623669 log_error "Failed to connect to the server"
624670 $server = nil
@@ -663,7 +709,7 @@ end
663709 #
664710 def main_loop
665711 while true
666- ret, = select([$server, $engine], nil, nil, 60)
712+ ret, = select([$engine, $server], nil, nil, 60)
667713 unless ret
668714 # Send keep-alive
669715 if $bridge_state.too_quiet?
@@ -673,12 +719,14 @@ def main_loop
673719 next
674720 end
675721
676- ret.each do |io|
677- case io
678- when $engine
679- $bridge_state.do_engine_recv
680- when $server
681- $bridge_state.do_sever_recv
722+ ret.each_with_index do |io, idx|
723+ if (!$options[:ignoremultiselect] || idx == 0)
724+ case io
725+ when $engine
726+ $bridge_state.do_engine_recv
727+ when $server
728+ $bridge_state.do_sever_recv
729+ end
682730 end
683731 end
684732
--- a/shogi-server
+++ b/shogi-server
@@ -208,7 +208,10 @@ def parse_command_line
208208 ["--least-time-per-move", GetoptLong::REQUIRED_ARGUMENT],
209209 ["--max-moves", GetoptLong::REQUIRED_ARGUMENT],
210210 ["--pid-file", GetoptLong::REQUIRED_ARGUMENT],
211- ["--player-log-dir", GetoptLong::REQUIRED_ARGUMENT])
211+ ["--player-log-dir", GetoptLong::REQUIRED_ARGUMENT],
212+ ["--tcpkeepalive-idle", GetoptLong::REQUIRED_ARGUMENT],
213+ ["--tcpkeepalive-intvl", GetoptLong::REQUIRED_ARGUMENT],
214+ ["--tcpkeepalive-cnt", GetoptLong::REQUIRED_ARGUMENT])
212215 parser.quiet = true
213216 begin
214217 parser.each_option do |name, arg|
@@ -283,6 +286,15 @@ def check_command_line
283286
284287 $options["least-time-per-move"] ||= ShogiServer::Default_Least_Time_Per_Move
285288 $options["least-time-per-move"] = $options["least-time-per-move"].to_i
289+
290+ $options["tcpkeepalive-idle"] ||= ShogiServer::Default_TcpKeepAlive_Idle
291+ $options["tcpkeepalive-idle"] = $options["tcpkeepalive-idle"].to_i
292+
293+ $options["tcpkeepalive-intvl"] ||= ShogiServer::Default_TcpKeepAlive_Intvl
294+ $options["tcpkeepalive-intvl"] = $options["tcpkeepalive-intvl"].to_i
295+
296+ $options["tcpkeepalive-cnt"] ||= ShogiServer::Default_TcpKeepAlive_Cnt
297+ $options["tcpkeepalive-cnt"] = $options["tcpkeepalive-cnt"].to_i
286298 end
287299
288300 # See if a file can be created in the directory.
@@ -455,8 +467,30 @@ def main
455467 server.start do |client|
456468 begin
457469 # client.sync = true # this is already set in WEBrick
458- client.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true)
459- # Keepalive time can be set by /proc/sys/net/ipv4/tcp_keepalive_time
470+ if Socket.const_defined?(:SOL_SOCKET) &&
471+ Socket.const_defined?(:SO_KEEPALIVE) &&
472+ Socket.const_defined?(:IPPROTO_TCP)
473+ client.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true)
474+ # Keepalive time can be set by /proc/sys/net/ipv4/tcp_keepalive_time
475+ if Socket.const_defined?(:TCP_KEEPIDLE) &&
476+ Socket.const_defined?(:TCP_KEEPINTVL) &&
477+ Socket.const_defined?(:TCP_KEEPCNT)
478+ client.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_KEEPIDLE, $options["tcpkeepalive-idle"])
479+ client.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_KEEPINTVL, $options["tcpkeepalive-intvl"])
480+ client.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_KEEPCNT, $options["tcpkeepalive-cnt"])
481+ elsif RUBY_PLATFORM.downcase =~ /mswin|mingw|cygwin|bccwin/
482+ # Windows 10 (1709 or later) ws2ipdef.h
483+ # https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-tcp-socket-options
484+ client.setsockopt(Socket::IPPROTO_TCP, 3, $options["tcpkeepalive-idle"])
485+ client.setsockopt(Socket::IPPROTO_TCP, 17, $options["tcpkeepalive-intvl"])
486+ client.setsockopt(Socket::IPPROTO_TCP, 16, $options["tcpkeepalive-cnt"])
487+ elsif RUBY_PLATFORM.downcase =~ /darwin/
488+ # macOS 10.12.6 (Sierra) /usr/include/netinet/tcp.h
489+ client.setsockopt(Socket::IPPROTO_TCP, 0x10, $options["tcpkeepalive-idle"])
490+ client.setsockopt(Socket::IPPROTO_TCP, 0x101, $options["tcpkeepalive-intvl"])
491+ client.setsockopt(Socket::IPPROTO_TCP, 0x102, $options["tcpkeepalive-cnt"])
492+ end
493+ end
460494 player, login = login_loop(client) # loop
461495 unless player
462496 log_error("Detected a timed out login attempt")
--- a/shogi_server.rb
+++ b/shogi_server.rb
@@ -50,6 +50,9 @@ Default_Timeout = 60 # for single socket operation
5050 Default_Game_Name = "default-1500-0"
5151 Default_Max_Moves = 256
5252 Default_Least_Time_Per_Move = 0
53+Default_TcpKeepAlive_Idle = 50
54+Default_TcpKeepAlive_Intvl = 5
55+Default_TcpKeepAlive_Cnt = 9
5356 One_Time = 10
5457 Login_Time = 300 # time for LOGIN
5558 Revision = "20201004"