ruby - 是否可以在不实际发送或读取数据的情况下查明 ruby​​ 套接字是否处于 ESTABLISHED 或 CLOSE_WAIT 状态?

标签 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

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

是用select()IO.select()还是其他方法完成的?

顺便说一句:套接字从不接收任何数据,它只是偶尔发送一些数据。

最佳答案

答案是implementation specific .您需要检查操作系统上的 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}"

这是我最新的 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;
};

您可能会注意到我的脚本只返回一个整数。这是详细说明 TCP 状态及其整数值的 C 枚举。同样,这是在/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 */
};  

此外,这 thread说你可以通过读取 EOF 来检测 CLOSE_WAIT。但由于您担心数据是否已发送,您可能需要解压缩到 tcpi_last_data_sent。

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

关于ruby - 是否可以在不实际发送或读取数据的情况下查明 ruby​​ 套接字是否处于 ESTABLISHED 或 CLOSE_WAIT 状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/879124/

相关文章:

javascript - Knockout.js 未正确设置选择选项

mysql - Rails-rake 数据库 :create error

ruby-on-rails - 如何跨规范文件重用 Rspec let 表达式?

c - 如何将链接目标添加到 Ruby mkmf?

ruby-on-rails - rails : how to show user's "last seen at" time?

javascript - 将 Socket.io 与 Node.js、Express 和 Jade 结合使用

android - 将套接字连接到设备上的本地地址

postgresql - 在 PostgreSQL 查询中返回超过 24 小时

sockets - 32 位 linux 上的同时 tcp/ip 连接数

php - 使用 PHP MySQL 从同一查询中的多个表中进行选择