shogi-server source
リビジョン | 5c8ecd515f4a0271af95433c1fb13a059320c63e (tree) |
---|---|
日時 | 2020-12-14 20:42:55 |
作者 | Mizar <mizar.jp@gmai...> |
コミッター | Mizar |
tcp_keepalive
@@ -103,7 +103,11 @@ def parse_command_line | ||
103 | 103 | ["--password", GetoptLong::REQUIRED_ARGUMENT], |
104 | 104 | ["--ponder", GetoptLong::NO_ARGUMENT], |
105 | 105 | ["--port", GetoptLong::REQUIRED_ARGUMENT], |
106 | - ["--floodgate", GetoptLong::NO_ARGUMENT]) | |
106 | + ["--floodgate", GetoptLong::NO_ARGUMENT], | |
107 | + ["--tcpkeepalive", GetoptLong::REQUIRED_ARGUMENT], | |
108 | + ["--tcpkeepalive-idle", GetoptLong::REQUIRED_ARGUMENT], | |
109 | + ["--tcpkeepalive-intvl", GetoptLong::REQUIRED_ARGUMENT], | |
110 | + ["--tcpkeepalive-cnt", GetoptLong::REQUIRED_ARGUMENT]) | |
107 | 111 | parser.quiet = true |
108 | 112 | begin |
109 | 113 | parser.each_option do |name, arg| |
@@ -131,6 +135,14 @@ def parse_command_line | ||
131 | 135 | options[:port] ||= ENV["PORT"] || 4081 |
132 | 136 | options[:port] = options[:port].to_i |
133 | 137 | options[:floodgate] ||= ENV["FLOODGATE"] || false |
138 | + options[:tcpkeepalive] ||= ENV["TCPKEEPALIVE"] || 0 | |
139 | + options[:tcpkeepalive] = options[:tcpkeepalive].to_i | |
140 | + options[:tcpkeepalive_idle] ||= ENV["TCPKEEPALIVE_IDLE"] || 50 | |
141 | + options[:tcpkeepalive_idle] = options[:tcpkeepalive_idle].to_i | |
142 | + options[:tcpkeepalive_intvl] ||= ENV["TCPKEEPALIVE_INTVL"] || 5 | |
143 | + options[:tcpkeepalive_intvl] = options[:tcpkeepalive_intvl].to_i | |
144 | + options[:tcpkeepalive_cnt] ||= ENV["TCPKEEPALIVE_CNT"] || 9 | |
145 | + options[:tcpkeepalive_cnt] = options[:tcpkeepalive_cnt].to_i | |
134 | 146 | |
135 | 147 | return options |
136 | 148 | end |
@@ -623,6 +635,30 @@ def login | ||
623 | 635 | begin |
624 | 636 | $server = TCPSocket.open($options[:host], $options[:port]) |
625 | 637 | $server.sync = true |
638 | + if $options[:tcpkeepalive] > 0 && | |
639 | + Socket.const_defined?(:SOL_SOCKET) && | |
640 | + Socket.const_defined?(:SO_KEEPALIVE) && | |
641 | + Socket.const_defined?(:IPPROTO_TCP) | |
642 | + $server.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true) | |
643 | + if Socket.const_defined?(:TCP_KEEPIDLE) && | |
644 | + Socket.const_defined?(:TCP_KEEPINTVL) && | |
645 | + Socket.const_defined?(:TCP_KEEPCNT) | |
646 | + $server.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_KEEPIDLE, $options[:tcpkeepalive_idle]) | |
647 | + $server.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_KEEPINTVL, $options[:tcpkeepalive_intvl]) | |
648 | + $server.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_KEEPCNT, $options[:tcpkeepalive_cnt]) | |
649 | + elsif RUBY_PLATFORM.downcase =~ /mswin|mingw|cygwin|bccwin/ | |
650 | + # Windows 10 (1709 or later) ws2ipdef.h | |
651 | + # https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-tcp-socket-options | |
652 | + $server.setsockopt(Socket::IPPROTO_TCP, 3, $options[:tcpkeepalive_idle]) | |
653 | + $server.setsockopt(Socket::IPPROTO_TCP, 17, $options[:tcpkeepalive_intvl]) | |
654 | + $server.setsockopt(Socket::IPPROTO_TCP, 16, $options[:tcpkeepalive_cnt]) | |
655 | + elsif RUBY_PLATFORM.downcase =~ /darwin/ | |
656 | + # macOS 10.12.6 (Sierra) /usr/include/netinet/tcp.h | |
657 | + $server.setsockopt(Socket::IPPROTO_TCP, 0x10, $options[:tcpkeepalive_idle]) | |
658 | + $server.setsockopt(Socket::IPPROTO_TCP, 0x101, $options[:tcpkeepalive_intvl]) | |
659 | + $server.setsockopt(Socket::IPPROTO_TCP, 0x102, $options[:tcpkeepalive_cnt]) | |
660 | + end | |
661 | + end | |
626 | 662 | rescue |
627 | 663 | log_error "Failed to connect to the server" |
628 | 664 | $server = nil |
@@ -208,7 +208,10 @@ def parse_command_line | ||
208 | 208 | ["--least-time-per-move", GetoptLong::REQUIRED_ARGUMENT], |
209 | 209 | ["--max-moves", GetoptLong::REQUIRED_ARGUMENT], |
210 | 210 | ["--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]) | |
212 | 215 | parser.quiet = true |
213 | 216 | begin |
214 | 217 | parser.each_option do |name, arg| |
@@ -283,6 +286,15 @@ def check_command_line | ||
283 | 286 | |
284 | 287 | $options["least-time-per-move"] ||= ShogiServer::Default_Least_Time_Per_Move |
285 | 288 | $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 | |
286 | 298 | end |
287 | 299 | |
288 | 300 | # See if a file can be created in the directory. |
@@ -455,8 +467,30 @@ def main | ||
455 | 467 | server.start do |client| |
456 | 468 | begin |
457 | 469 | # 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 | |
460 | 494 | player, login = login_loop(client) # loop |
461 | 495 | unless player |
462 | 496 | log_error("Detected a timed out login attempt") |
@@ -50,6 +50,9 @@ Default_Timeout = 60 # for single socket operation | ||
50 | 50 | Default_Game_Name = "default-1500-0" |
51 | 51 | Default_Max_Moves = 256 |
52 | 52 | Default_Least_Time_Per_Move = 0 |
53 | +Default_TcpKeepAlive_Idle = 50 | |
54 | +Default_TcpKeepAlive_Intvl = 5 | |
55 | +Default_TcpKeepAlive_Cnt = 9 | |
53 | 56 | One_Time = 10 |
54 | 57 | Login_Time = 300 # time for LOGIN |
55 | 58 | Revision = "20160409" |