2012-04-19 13 views
7

La mia applicazione C# .NET fa attualmente i seguenti (tra le altre cose):socket non si chiude dopo chiusura dell'applicazione se un processo avviato è aperta

  1. crea un thread che si apre un socket su una porta specifica e aspetta un'istruzione
  2. Il messaggio arriva, il thread di socket legge il messaggio e genera un evento.
  3. Un gestore eventi chiama le funzioni necessarie per analizzare il messaggio ed esegue l'azione necessaria, ad esempio avviando un'applicazione.
  4. L''"applicazione" esterna specificata viene avviata in modo asincrono.

Quando la mia applicazione si riavvia, ma l'applicazione esterna non si chiude, il socket sembra non chiudersi mai. Quindi quando provo ad avviare la comunicazione su quella porta, ricevo un errore. Tuttavia, non appena chiudo l'applicazione esterna riesco ad aprire un socket su quella porta.

Sembra che il mio programma non si chiuda correttamente. Dovrebbe essere uccidere il socket quando esce, tuttavia quando il processo esterno è in esecuzione, quel socket non si chiude mai.

Qualche idea?

+0

Si sta smaltendo la presa? –

+0

Come stai gestendo il processo esterno? Si prega di inviare un po 'di codice. – zmbq

+0

@ M.Babcock Sì, sto chiudendo il socket e ho verificato che il codice venga eseguito quando l'interfaccia utente è chiusa. Sto usando un TcpClient e un TcpListener. Il client viene "chiuso" e l'ascoltatore viene "fermato". Tuttavia, questo non sembra liberare la porta. – JSideris

risposta

13

Questa è solo una pugnalata perché ho visto come stai iniziando il processo esterno. Se si sta creando un oggetto di processo, la mia ipotesi è che non sta impostando:

ProcessStartInfo.UseShellExecute = true; 

Se UseShellExecute è impostato su false, il processo figlio erediterà socket aperto gestisce dal processo genitore. Ciò manterrà il socket aperto anche se l'applicazione genitore è chiusa.

+0

Proprio sul denaro. UseShellExecute è stato impostato su false in modo da poter reindirizzare/disporre dei flussi di input. Dopo aver eliminato il reindirizzamento e aver impostato UseShellExecute su true, le porte vengono liberate. Grazie! – JSideris

+0

Contento di aver potuto aiutare. Ci siamo appena imbattuti in questo problema circa un mese fa. Abbiamo ricevuto un errore di socket dopo un errore di socket anche quando gli oggetti si stavano smaltendo correttamente. Fortunatamente uno dei ragazzi qui ha trovato sepolto da qualche parte su MSDN. – Josh

+0

uguale a [http://stackoverflow.com/a/24677139/4123833](http://stackoverflow.com/a/24677139/4123833), contiene altre due soluzioni/opzioni. – aspark

0

Potreste essere in grado di risolvere questo con la parola chiave utilizzando

using (Socket socket = new Socket()) { 
//The code 
} 

Ha l'altra applicazione utilizza il socket a tutti?

+0

L'altra applicazione non utilizza la presa. Lo sto testando con un'applicazione casuale sul mio sistema ... ad esempio Firefox. – JSideris

+0

Giusto per essere sicuri - se non si apre un'applicazione esterna, il problema si presenta quindi rilasciare la presa? – Anders

+0

Sì, il socket viene rilasciato quando l'app esterna non viene avviata. – JSideris

1

Da quello che ho trovato here il mio sospetto potrebbe essere confermato che questo è un caso del nuovo processo che eredita gli handle dal genitore, causando così il problema.

Sembra che sia possibile copiare/incollare il codice da quel collegamento per effettuare una chiamata diretta all'API di Windows CreateProcess con il flag impostato in modo da non ereditare gli handle.

Un'altra idea separata è scrivere un programma di avvio intermedio che raccolga le informazioni della riga di comando, quindi si lanci e quindi si chiuda. Questo extraindirizzamento potrebbe portarti dove devi essere con pochissimo sforzo.

+0

Sembra che 'cmd' sia adatto per un _intermediate launcher_ con un minimo sforzo. –

0

La prima cosa è dare un'occhiata allo stato del socket quando l'applicazione è chiusa. Il socket potrebbe essere nello stato TIME_WAIT che significa che aspetterà per un po 'di tempo per assicurarsi che non vengano ricevuti altri messaggi. È possibile leggere qui: http://www.isi.edu/touch/pubs/infocomm99/infocomm99-web/ Ora lo stato TIME_WAIT verrà generato sul socket in base al quale è stata avviata la procedura di terminazione della connessione. Quindi se per qualche ragione il tuo socket esegue l'azione vicina nel sito del server, allora nel sito del server (nella porta del server) il socket cambierà lo stato in TIME_WAIT, quindi se riavvii l'applicazione server durante il socket è in TIME_WAIT a nuovo socket non riuscirà a collegarsi alla porta di ascolto, io sono certo che questo è il problema che hai incontrato.

Problemi correlati