Questo sito utilizza cookies, anche di terze parti, per mostrare pubblicità e servizi in linea con il tuo account. Leggi l'informativa sui cookies.
Username: Password: oppure
C# / VB.NET - [C#] Fermare thread di connessioni socket in ascolto
Forum - C# / VB.NET - [C#] Fermare thread di connessioni socket in ascolto

Avatar
Roby94 (Member)
Guru


Messaggi: 1127
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 19:54
Mercoledì, 17/10/2012
Salve, ho dovuto fare una piccola divergenza dai mio calssico sviluppo PHP per creare un server da utilizzare con i websocket di HTML5, lo sviluppo sembra andare bene avrei solo un piccolo problema quando cerco di fermare il server:
Codice sorgente - presumibilmente C++

  1. //avvio[...]//
  2.         static void start()
  3.         {
  4.             if (serverActive == false)
  5.             {
  6.                 try
  7.                 {
  8.                     server.Start();
  9.                     listenerThread = new Thread(new ThreadStart(listener));
  10.                     listenerThread.Start();
  11.                     serverActive = true;
  12.                     Console.WriteLine("Il server è stato avviato.");
  13.                 }
  14.                 catch
  15.                 {
  16.                     Console.WriteLine("Errore nell' avvio del server.");
  17.                 }
  18.             }
  19.             else Console.WriteLine("Il server è gia avviato.");
  20.         }
  21.  
  22.         static void stop()
  23.         {
  24.             if (serverActive == true)
  25.             {
  26.                 foreach (Client c in clients)
  27.                 {
  28.                     try
  29.                     {
  30.                         c.Send("Il server si sta spegnendo. Arrivederci!");
  31.                         c.client.Close();
  32.                     }
  33.                     catch { }
  34.                 }
  35.                 clients.Clear();
  36.                 listenerActive = false;
  37.                 listenerThread.Abort();//L'errore sta qua
  38.                 server.Stop();
  39.                 serverActive = false;
  40.                 Console.WriteLine("Il server è stato arrestato.");
  41.             }
  42.             else Console.WriteLine("Il server non è in esecuzione.");
  43.         }
  44.  
  45.         static void listener()
  46.         {
  47.             listenerActive = true;
  48.             while (listenerActive)
  49.             {
  50.                 Socket client = server.AcceptSocket();
  51.                 if (clients.Count < 2)
  52.                 {
  53.                     clients.Add(new Client(client));
  54.                     Console.WriteLine("Utenti connessi: " + clients.Count);
  55.                 }
  56.                 else
  57.                 {
  58.                     client.Send(ascii.GetBytes("Server Pieno!"));
  59.                     Console.WriteLine(client.RemoteEndPoint.ToString() + " connessione rifiutata per limite utenti");
  60.                     client.Close();
  61.                 }
  62.                 Thread.Sleep(10);
  63.             }
  64.         }
  65. //Classe Client[...]//


Quando eseguo il metodo stop l'applicazione va in blocco nel punto che ho segnato, me ne accorgo dal fatto che il messaggio di conferma dell' arresto del server non viene stampato. Sono nuovo dei thread e credo che la mancanza di esperienza mi penalizzi un po, ho provato anche a interrompere il ciclo while ma sembra che esso continui ad oltranza probabilemnte perche si trova in un thread separato. Mi sapete aiutare?
P.S. Se ho fatto qualche errore madornale nello sviluppo del server me lo potreste segnalare, mi fareste un grnade piacere
Grazie in anticipo


La programmazione è arte... fa che i tuoi script siano degni di un museo.
PM Quote
Avatar
tasx (Dev Team)
Expert


Messaggi: 439
Iscritto: 15/12/2008

Segnala al moderatore
Postato alle 20:40
Mercoledì, 17/10/2012
Ciao puoi postare l'eccezione che ti viene scatenata?

Ciaociao :k:


... sei un proxy che perde i pacchetti ...
PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1127
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 20:50
Mercoledì, 17/10/2012
nessuna eccezione se uso Abort, è proprio quello il problema... sinceramente non capisco... se invece tolgo l'abort l'eccezione che viene generata da Socket client = server.AcceptSocket(); è SocketException e per l'appunto cerco di stoppare il while ed eliminare il thread per evitare che si verifichi. Se avete bisogno che posti tutto il codice ditemelo, ma credo che queste righe bastino.


La programmazione è arte... fa che i tuoi script siano degni di un museo.
PM Quote
Avatar
tasx (Dev Team)
Expert


Messaggi: 439
Iscritto: 15/12/2008

Segnala al moderatore
Postato alle 21:41
Mercoledì, 17/10/2012
Scusa ma il metodo start avvia un nuovo thread e poi? è dentro un altro ciclo? o c'è qualcosa che interrompe l'esecuzione?

Per la gestione delle variabili con accesso da più thread o le dichiari "volatile" o usi il sistema dei lock....
Teoricamente i thread non andrebbero "abortiti" (:rofl: :rofl: che termini...), per terminarli è sufficiente far terminare il metodo passato come threadstart...

Comunque ti consiglio di usare i Task che sono nuovi e molto più comodi....


... sei un proxy che perde i pacchetti ...
PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1127
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 22:07
Mercoledì, 17/10/2012
Allora con start avvio il server e creo un nuovo thread che controlla se vi sono connessioni al server attraverso un while(ho usato un nuovo thread appunto perche se no l'applicazione andava in loop con quel while(true) ed avevo bisogno che la console rimanesse utilizzabile per dare istruzioni al server)
Codice sorgente - presumibilmente C#

  1. static void Main(string[] args)
  2.         {
  3.             start();
  4.             readConsole();
  5.         }
  6.  
  7.         static void readConsole() {
  8.             String s = Console.ReadLine();
  9.             switch(s) {
  10.                 case ">>start":
  11.                     start();
  12.                 break;
  13.                 case ">>stop":
  14.                     stop();
  15.                 break;
  16.             }
  17.             readConsole();
  18.         }


Poi ho pensato; allo stop del server elimino il thread con abort (da qui il l'italianizzato "Abortire" :rofl:) in questo modo il metodo AcceptSocket non crea eccezioni... visto che non funzionava ho introdotto listenerActive in modo che cambiando il suo valore in false il ciclo si interrompesse per poi eliminare il thread ma anche cosi nada...
La mia idea di eliminare il thread veniva dal fatto che pensavo che al riavvio il server il creare un nuovo thread con lo stesso metodo comportasse dei conflitti.... è un idea sbagliata? Basta mettere il thread in pausa e dichiararne uno nuovo quando serve?
Comunque provo a vedere se trovo anche della documentazione su i Task che attualmente non conosco.
Grazie ;)


La programmazione è arte... fa che i tuoi script siano degni di un museo.
PM Quote
Avatar
tasx (Dev Team)
Expert


Messaggi: 439
Iscritto: 15/12/2008

Segnala al moderatore
Postato alle 22:27
Mercoledì, 17/10/2012
Allora secondo me ti conviene ripensare l'applicazione...

1) non usare tutti i metodi statici (mi hai fatto venire il mal di pancia ;) ;) ), crei un oggetto e poi nel Main gli dai un bel
Codice sorgente - presumibilmente C# / VB.NET

  1. new oggettoCheHaiCreato();



2) occhio al metodo readConsole(), non penso sia la soluzione migliore utilizzare la ricorsività... usa al massimo un while(anzi ti obbligo ad usarlo ;) )

3) nel thread principale(ovvero quello del Main) accetti i socket, una volta accettato il socket allora crei un nuovo thread passadogli il socket, o al massimo usi un task(sempre se usi .net 4.5) altrimenti nada, o forse anche 4.0, devo controllare).
Codice sorgente - presumibilmente C# / VB.NET

  1. // un esempio di task
  2. void startTask()
  3. {
  4.    for(int i = 0; i < 100; i++)
  5.    {
  6.         new Task(() => {
  7.                 Console.WriteLine("task started...");
  8.             }).start();
  9.    }
  10. }



si la soluzione con listeneractive ha senso però il thread è fermo su AcceptSocket quindi quando la setti a false
lui non termina e dunque ti salta l'eccezione, è per questo che ti consiglio di accettare i socket nel thread principale e poi assegnare un client ad ogni nuovo thread...

ciaociao :k:


... sei un proxy che perde i pacchetti ...
PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1127
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 23:15
Mercoledì, 17/10/2012
1)Ahahah tranqui è solo provvisorio, prima di creare le classi di argomenti che non conosco bene faccio sempre cosi, per organizzarle meglio ;) cosi quando le compongo parto da un codice gia finito
2) Essi speravo pure io di farlo in while solo che non ero sicuro di come ma adesso ho trovato basta metterlo su true, avevo paura di inviare 50000 readline :rofl: (non mi era mai capitato di dover tenere in acolto la console)
3) ok ma se metto l'accettazione dei socket sul main non rischio di bloccare l'appplicazione come ho menzionato prima?
grazie che mi hai spiegato il problema di listeneractive adesso ho capito ;)
Senti ma devo proprio creare un thread per ogni client o posso tenere come è ora
Codice sorgente - presumibilmente Delphi

  1. class Client
  2.         {
  3.             public Socket client;
  4.             protected EndPoint ip;
  5.  
  6.             public Client(Socket client)
  7.             {
  8.                 this.client = client;
  9.                 this.ip = client.RemoteEndPoint;
  10.                 Console.WriteLine(this.ip.ToString() + " connesso al server");
  11.                 this.client.Send(ascii.GetBytes("Benvenuto!"));
  12.                 Thread listenerThread = new Thread(new ThreadStart(this.listener));
  13.                 listenerThread.Start();
  14.             }
  15.  
  16.             protected void listener()
  17.             {
  18.                 while (true)
  19.                 {
  20.                     try
  21.                     {
  22.                         byte[] buffer = new byte[client.Available];
  23.                         this.client.Receive(buffer);
  24.                         Console.WriteLine("<" + this.ip + "> " + Encoding.Default.GetString(buffer));
  25.                         foreach (Client c in clients)
  26.                         {
  27.                             c.Send("<" + this.ip + "> " + buffer.ToString());
  28.                         }
  29.                     }
  30.                     catch { }
  31.                     Thread.Sleep(10);
  32.                 }
  33.             }
  34.  
  35.             public void Send(String message)
  36.             {
  37.                 this.client.Send(ascii.GetBytes(message));
  38.             }
  39.         }


con la classe Client?

avevo scritto un messaggio molto completo ma poi il server mi ha tirato un brutto scherzo -_-


La programmazione è arte... fa che i tuoi script siano degni di un museo.
PM Quote