2011-01-14 3 views
8

Citando this socket tutorial:passivi e attivi prese

Sockets sono di due tipi principali. Una presa attivo è collegato ad una presa remota attiva tramite una connessione dati aperte connessione ... Un socket passivo è non connesso, ma piuttosto attende una connessione in ingresso , che generare una nuova presa attiva dopo una connessione è stabilito ...

ciascuna porta può avere un singolo socket passivo binded ad esso, in attesa connessioni in entrata e prese multiple attive, ciascuna corrispondente ad un connessione aperta sulla porta. E 'come se l'operaio è in attesa di nuovi messaggi per arrivare (egli rappresenta il socket passivo), e quando uno messaggio arriva da un nuovo mittente, ha inizia una corrispondenza (una connessione ) con loro da delegante qualcun altro (un socket attivo ) per leggere effettivamente il pacchetto e rispondere al mittente se è necessario . Ciò consente al lavoratore di fabbrica di essere libero di ricevere nuovi pacchetti . ...

Poi il tutorial spiega che, dopo una connessione viene stabilita, la presa attiva continua la ricezione dei dati finché non ci sono altri byte, e quindi chiude la connessione.

Ciò che non ho capito è questo: supponiamo che ci sia una connessione in ingresso alla porta e che il mittente voglia inviare alcuni piccoli dati ogni 20 minuti. Se il socket attivo chiude la connessione quando non ci sono byte rimanenti, il mittente deve riconnettersi alla porta ogni volta che vuole inviare i dati? Come manteniamo una connessione una volta stabilita per un tempo più lungo? Puoi dirmi cosa mi manca qui?

La seconda domanda è: chi stabilisce il limite delle prese attive che funzionano contemporaneamente?

+1

Stai parafrasando quell'articolo e prendi pezzi da diverse sezioni dell'articolo. I contesti sono diversi. Nell'ultima sezione l'autore sta spiegando il suo programma. Le prese non funzionano così di default, infatti se si dimentica di chiudere il socket, le cose brutte possono accadere. Il socket non si chiude automaticamente quando riceve l'ultimo byte. – SRM

+0

OK, ho pensato che fosse la convention e ho solo chiesto cosa mi manca qui. Sono nuovo per i concetti ed è per questo che voglio mettere in discussione tutto ciò che trovo difficile da capire. – aslisabanci

+0

Nessun problema, volevo solo assicurarmi che capissi che devi chiudere esplicitamente il socket. Potrebbe salvarti qualche mal di testa lungo la linea quando ti grattano la testa cercando di capire perché la presa non si chiude :). – SRM

risposta

6

Il mittente deve inviare un pacchetto KEEPALIVE a intervalli regolari per mantenere in vita la connessione. Il formato di KEEPALIVE dipende dal protocollo. Potrebbe essere piccolo come un singolo NULL nel segmento di dati TCP.

Per quanto riguarda la seconda domanda ... dipende dall'I/O. Se si sta bloccando l'I/O, si desidera solo un determinato numero di thread in esecuzione sul computer, quindi non sarà possibile avere molti client. Se non è bloccante, puoi avere molti più clienti. I linguaggi di programmazione dovrebbero supportare sia l'I/O di blocco che quello non bloccante. (So ​​per certo che Java lo fa.)

Dipende anche da cose come larghezza di banda, trasferimento dati per ogni cliente, memoria, velocità di clock, ecc. Ma il blocco non bloccante e il blocco possono fare un'enorme differenza il numero di clienti che puoi accettare. Probabilmente non puoi avere più di 5-10 client bloccati senza il crash del tuo server ... ma puoi avere migliaia se non stai bloccando.

+0

In questo modo, l'invio continuo di questi pacchetti keepalive per 20 minuti è un'operazione meno costosa rispetto al ripristino della connessione ogni volta? Quali sarebbero i vantaggi di mantenere in vita la connessione, oltre a sfuggire al sovraccarico della riconnessione? – aslisabanci

+1

In realtà se ci sono molti client che si connettono e ogni richiesta sarà veloce (20 secondi come hai detto tu) allora è meglio usare un modello di tipo richiesta/risposta. Sono disponibili solo 64k di porte, il che significa che possono essere accettati solo 64k socket su un IP prima di esaurire la porta a meno che tali socket non siano chiusi. Tuttavia dipende molto dalla tua applicazione. Ad esempio, se stai scrivendo un MMO, hai bisogno di connessioni persistenti. Se stai scrivendo un server web, anche se non ti serviranno (e cercherò di evitare) le connessioni persistenti (a meno che tu non stia utilizzando HTML5 ma questa è una storia diversa). – SRM

+2

Dal punto di vista del cliente, un semplice keepalive per un singolo server non richiede molto lavoro. Probabilmente stai già inviando regolarmente una mezza dozzina di keepalive quando sei connesso a Internet. Dal punto di vista del server, potrebbe essere vantaggioso mantenere il numero di socket nella sua lista socket almeno, per migliorare le prestazioni I/O. Se è necessario attendere fino a 20 minuti tra i trasferimenti di dati, creerei una nuova connessione ogni volta. È trascurabile per il client, ma non per il server. – ktm5124

0

Prima domanda: Sì, una volta chiuso un socket, è necessario eseguire un Open per riavviare la comunicazione.

Seconda domanda: Sì.Se vuoi puoi creare 64k connessioni al tuo server e soffrire di esaurimento della porta (non lo consiglio). Come ha affermato ktm5124, tutto dipende dalla tua applicazione. Esistono diversi modi per rendere scalabile il server, incluso l'I/O asincrono e/o un pool di thread per gestire le richieste dei client.

+0

Vedere la risposta di Will http://stackoverflow.com/a/2332756/1418457 forse si fraintende qualcosa sul TCP – onmyway133

+0

Ok, se l'esaurimento della porta tcp/ip è solo una cosa lato client (come indicato dal limite di 64k per client per porta del server), quindi perché esiste un problema del mondo reale dell'esaurimento delle porte sui server? Puoi ancora utilizzare tutti i valori della tupla - forse il mio numero di 64k è sbagliato, ma c'è un limite rigido al numero di combinazioni che la tupla può contenere. Quando si esauriscono le combinazioni, a meno che non si riutilizzi l'indirizzo, si esauriranno gli indirizzi (veramente una tupla unica) per assegnare la connessione in entrata e la connessione viene rifiutata. – SRM

3

Si prega di non confondere i pacchetti effettivi inviati dall'implementazione TCP/IP sulla rete e l'interazione tra il programma e una libreria che implementa il protocollo TCP/IP.

Il socket è solo un'astrazione che viene presentata al programma dall'implementazione TCP/IP (libreria o sistema operativo del kernel). È possibile visualizzare socket come connessione alla pipe (localIP: port-remoteIP: port). Il tuo programma apre socket, comunica i dati tramite socket e può chiudere il socket se non è più necessario per aiutare le risorse gratuite. Questo è il flusso normale. Tuttavia, l'implementazione TCP/IP potrebbe chiudere il socket per i propri motivi validi. Alcuni di questi motivi: disconnessione del cavo di accesso alla rete, errori di instradamento della rete, server andato giù, ecc. Così il tuo programma potrebbe trovare il socket tcp/ip chiuso anche se non lo chiudeva.

Ora la tua prima domanda, cosa devo fare se il mio programma invia piccoli segmenti di dati con una lunga pausa tra di loro. La risposta è: dipende da quanto è lunga la pausa e quale programma ti ascolta dall'altra parte. La maggior parte delle implementazioni TCP/IP ha una nozione di timeout della connessione per fornire astrazioni di connessione affidabile su reti reali inaffidabili. Quindi se il tuo programma si fermerà più a lungo del timeout di tcp/ip, troverai il tuo socket chiuso dalla libreria e dovrai riaprire il socket. Ciò potrebbe anche causare di nuovo il riavvio della comunicazione, dipende da un programma che ti ascolta dall'altra parte della pipe di connessione TCP/IP.

Ci sono modi per aumentare il timeout di tcp/ip e mantenerlo in vita. Questi possono essere fatti come parte della configurazione di rete, la configurazione del software del server da un'altra parte o chiedendo esplicitamente di mantenere aperto il socket impostando i parametri KEEPALIVE nella chiamata alla libreria tcp/ip. Sarebbe ancora aperto o non dipende. I dettagli completi su come tcp/ip manterrebbe il socket aperto non ti confonderanno poiché non ha nulla a che fare con il tuo codice. TCP/IP ha molte impostazioni e diversi timeout per fornire al tuo programma l'illusione di una connessione stabile e affidabile. La parte migliore è tutto nascosto dal codice del tuo programma, purché non ne abusi. Mantieni la tua pausa in pochi secondi :) Un set di impostazioni di timeout potrebbe funzionare bene per piccole applicazioni in una rete locale affidabile e non funzionerà con applicazioni a carico elevato o su connettività cross-continent. Ogni situazione specifica ha la sua soluzione, spesso più di una sola.

In questa specifica domanda "per inviare alcuni piccoli dati ogni 20 minuti" vorrei consigliare di chiudere e aprire la connessione socket per ogni comunicazione. Il tempo per aprirne uno è meno di un secondo e non dovrebbe influire sulla tua comunicazione. In cambio si ottiene meno complessità nel protocollo di comunicazione. Il ricevitore si avvia sempre con una nuova connessione socket ed entrambi i sistemi possono usufruire di risorse gratuite nella comunicazione tcp/ip su tutti i 20 minuti quando non sono necessari.