2009-05-18 4 views
5
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 или если он вошел в CLOSE_WAIT после дефолта 7200 секунд или даже хуже, был закрыт, фактически не нуждаясь в .write() на или .read().можно узнать, находится ли рубиновый сокет в состоянии ESTABLISHED или CLOSE_WAIT без фактической отправки или чтения данных?

Выполнено ли с select(), IO.select() или другим способом?

BTW: Сокет никогда не получает никаких данных, которые он просто посылает иногда.

ответ

9

Ответ 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}" 

Вот tcp_info структура для моего уточненного Ubuntu Linux

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; 
}; 

Вы можете заметить, что мой скрипт только возвращает целое число. Вот список C, который описывает состояния 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 */ 
}; 

Кроме того, это thread говорит, что вы можете обнаружить CLOSE_WAIT чтения EOF. Но поскольку вас беспокоит, были ли отправлены данные, вам, вероятно, придется распаковать до tcpi_last_data_sent.

И, наконец, оговорка. Я взял на себя задачу ответить на ваш вопрос, потому что это звучало весело, и это было только мои ноги C все еще шатались, поэтому YMMV. :)