2009-05-18 11 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 

Da qui in poi desidera effettuare il check in un thread, se la connessione SSL e la presa di fondo è ancora ESTABLISHED o se è andato in CLOSE_WAIT dopo il default di 7200 secondi o anche peggio ricevuti chiusi senza in realtà bisogno di .write() a o .read() da esso.è possibile scoprire se un socket rubino è in stato ESTABLISHED o CLOSE_WAIT senza effettivamente inviare o leggere dati?

È stato eseguito con select(), IO.select() o un altro metodo?

BTW: La presa non riceve mai dati che invia occasionalmente.

risposta

9

La risposta è implementation specific. Dovrai controllare i file di intestazione dell'implementazione di TCP sul tuo sistema operativo. Ecco un client di esempio per linux che restituisce lo stato del socket.

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

Ecco lo struct tcp_info per il mio up-to-date 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; 
}; 

Si può notare che il mio script restituisce solo un numero intero. Ecco il C enum che descrive gli stati TCP e i loro valori interi. Di nuovo, questo è stato trovato in /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 */ 
}; 

Inoltre, questo thread dice che è possibile rilevare CLOSE_WAIT leggendo EOF. Ma dal momento che sei preoccupato che i dati siano stati inviati, probabilmente dovrai decomprimere fino a tcpi_last_data_sent.

Infine, un avvertimento. Ho accettato la sfida di rispondere alla tua domanda perche 'suonava divertente ed e' stato ma le mie gambe a C sono ancora traballanti quindi YMMV. :)

Problemi correlati