是否可以找出ruby套接字是否处于ESTABLISHED或CLOSE_WAIT状态而不实际发送或读取数据?

5 ruby sockets select openssl

s = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
s.connect(Socket.pack_sockaddr_in('port', 'hostname'))

ssl = OpenSSL::SSL::SSLSocket.new(s, sslcert)
ssl.connect
Run Code Online (Sandbox Code Playgroud)

从这里开始,我想检查一个线程,如果ssl连接和底层套接字仍然存在,ESTABLISHED或者它是否CLOSE_WAIT在默认值7200秒之后进入,或者更糟糕的是关闭而不需要实际需要.write().read()来自它.

是否与完成select(),IO.select()或另一种方法?

BTW:套接字永远不会收到它偶尔发送的任何数据.

Jon*_*ace 10

答案是具体实施.您需要检查操作系统上的tcp实现头文件.这是一个返回套接字状态的linux示例客户端.

  ts = TCPSocket.new('localhost', 5777)
  ssl = OpenSSL::SSL::SSLSocket.new(ts, OpenSSL::SSL::SSLContext.new)
  ssl.sync = true
  ssl.connect
  # TCP_INFO is 11
  # note that TCP_INFO isn't defined in the ruby source.  
  # i had to look up the integer value in /usr/include/netinet/tcp.h
  optval = ts.getsockopt(Socket::SOL_TCP, 11) 
  state = optval.unpack "i" 
  puts "state: #{state}"
Run Code Online (Sandbox Code Playgroud)

这是我最新的ubuntu linux的tcp_info结构

struct tcp_info
{
  u_int8_t      tcpi_state;
  u_int8_t      tcpi_ca_state;
  u_int8_t      tcpi_retransmits;
  u_int8_t      tcpi_probes;
  u_int8_t      tcpi_backoff;
  u_int8_t      tcpi_options;
  u_int8_t      tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4;

  u_int32_t     tcpi_rto;
  u_int32_t     tcpi_ato;
  u_int32_t     tcpi_snd_mss;
  u_int32_t     tcpi_rcv_mss;

  u_int32_t     tcpi_unacked;
  u_int32_t     tcpi_sacked;
  u_int32_t     tcpi_lost;
  u_int32_t     tcpi_retrans;
  u_int32_t     tcpi_fackets;

  /* Times. */
  u_int32_t     tcpi_last_data_sent;
  u_int32_t     tcpi_last_ack_sent;     /* Not remembered, sorry.  */
  u_int32_t     tcpi_last_data_recv;
  u_int32_t     tcpi_last_ack_recv;

  /* Metrics. */
  u_int32_t     tcpi_pmtu;
  u_int32_t     tcpi_rcv_ssthresh;
  u_int32_t     tcpi_rtt;
  u_int32_t     tcpi_rttvar;
  u_int32_t     tcpi_snd_ssthresh;
  u_int32_t     tcpi_snd_cwnd;
  u_int32_t     tcpi_advmss;
  u_int32_t     tcpi_reordering;

  u_int32_t     tcpi_rcv_rtt;
  u_int32_t     tcpi_rcv_space;

  u_int32_t     tcpi_total_retrans;
};
Run Code Online (Sandbox Code Playgroud)

您可能会注意到我的脚本只返回一个整数.这是C enum,详细说明了TCP状态及其整数值.同样,这可以在/usr/include/netinet/tcp.h中找到

enum
{   
  TCP_ESTABLISHED = 1,          
  TCP_SYN_SENT,
  TCP_SYN_RECV,
  TCP_FIN_WAIT1,
  TCP_FIN_WAIT2,
  TCP_TIME_WAIT,
  TCP_CLOSE,
  TCP_CLOSE_WAIT,
  TCP_LAST_ACK,
  TCP_LISTEN, 
  TCP_CLOSING   /* now a valid state */
};  
Run Code Online (Sandbox Code Playgroud)

此外,该线程表示您可以通过读取EOF来检测CLOSE_WAIT.但由于您担心数据是否已发送,因此您可能需要解压缩到tcpi_last_data_sent.

最后,一个警告.我接受了回答你的问题的挑战,因为它听起来很有趣,但是我的C腿仍然不稳定所以YMMV.:)