[C#] Mon service ne s'arrête plus

MagicBuzz Messages postés 4 Date d'inscription dimanche 18 juillet 2004 Statut Membre Dernière intervention 19 novembre 2005 - 18 juil. 2004 à 13:00
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019 - 18 juil. 2004 à 19:00
Bonjour, je suis en train de développer un jeu de type MUD (faire une recherche dans www.mud-connect.com pour plus d'infos).

Le jeu tourne donc en tant que sevice Windows, et attends des connections telnet.

Au départ, avant d'intégrer la partie des sockets, j'ai recopié l'exemle du tutorial de MSDN à propos des threads (mes sessions telnet sont dans des threads afin de ne pas bloquer l'éxécution de la routine principale du service)

En créant un thread dans le OnStart() du service, puis en le stopant avec Abort() puis Join() dans le OnStop() ca fonctionnait très bien (de même avec OnPause() et OnResume())

Seulement, depuis que mon thread contient des appels à Socket, il refuse de mourrir, je suis obligé de shooter le service via le gestionnaire des tâches pour arrêter le service.

Ci-dessous mon code :

Service1.cs:

Code :


namespace MagicMUD
{
public class Service1 : System.ServiceProcess.ServiceBase
{
Thread oThread;

protected override void OnStart(string[] args)
{
EventLog.WriteEntry("MagicMUD", "Service launching", EventLogEntryType.Information, 1);

Server oServer = new Server();
oThread = new Thread(new ThreadStart(oServer.StartServer));
oThread.Start();

while (!oThread.IsAlive);
}

protected override void OnStop()
{
EventLog.WriteEntry("MagicMUD", "Service finishing", EventLogEntryType.Information, 4);
oThread.Abort();
oThread.Join();
}
}
}



Server.cs:

Code :


using System;
using System.Diagnostics;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace MagicMUD
{
public class Server
{
private Socket s;
private Thread oThread;

public Server()
{
}

~Server()
{
EventLog.WriteEntry("MagicMUD", "Je suis dans le destructeur du Server", EventLogEntryType.Information, 1001);

if (s.Connected)
{
s.Shutdown(SocketShutdown.Both);
s.Close();
}

if (oThread.IsAlive)
{
oThread.Abort();
oThread.Join();
}
}

public void StartServer()
{

s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint ipe = new IPEndPoint(ipAddress, 80);

try
{
s.Bind(ipe);
s.Listen(100);
}
catch (SocketException se)
{
EventLog.WriteEntry("MagicMUD", "Socket error : " + se.ToString(), EventLogEntryType.Error, 101);
return;
}

while (true)
{
Socket handler;
try
{
handler = s.Accept();
EventLog.WriteEntry("MagicMUD", "Nouvelle connection", EventLogEntryType.Information, 1002);
}
catch (SocketException se)
{
EventLog.WriteEntry("MagicMUD", "Socket error : " + se.ToString(), EventLogEntryType.Error, 102);
break;
}

if (handler.Connected)
{
Session oSession = new Session(handler);
oThread = new Thread(new ThreadStart(oSession.Run));
oThread.Start();
}
else
{
EventLog.WriteEntry("MagicMUD", "Error. Client disconnected before session starts", EventLogEntryType.Error, 103);
return;
}
}
}
}

public class Session
{
private Socket handler;

public Session(Socket handler)
{
this.handler = handler;
}

~Session()
{
if (this.handler.Connected)
{
this.handler.Shutdown(SocketShutdown.Both);
this.handler.Close();
}
}

public void Run()
{
string dataRcp = null;

while (true)
{
while (true)
{
byte[] bytes = new byte[256];
int bytesRec = handler.Receive(bytes);
dataRcp += Encoding.ASCII.GetString(bytes, 0, bytesRec);
if (dataRcp.IndexOf("\n") > -1)
{
break;
}
}
EventLog.WriteEntry("MagicMUD", "J'ai reçu ça : " + dataRcp, EventLogEntryType.Information, 1001);
byte[] msg = Encoding.ASCII.GetBytes(dataRcp);
handler.Send(msg);
if (dataRcp.IndexOf("quit") == 0)
{
EventLog.WriteEntry("MagicMUD", "Arrêt de la connection", EventLogEntryType.Information, 1003);
break;
}
dataRcp = null;
}

if (this.handler.Connected)
{
this.handler.Shutdown(SocketShutdown.Both);
this.handler.Close();
}
}
}
}


PS: Deplus, dans mon thread "Server", je voudrais stocket mes "Session", mais un tableau ne me semble pas terrible, car il va vite y avoir des trous (quand un joueur se déconnecte) et il faudra redimensionner le tableau à chaque nouvelle connection...
Y'a pas un objet collection avec "Add()" et "Remove()" accessible avec foreach ?

Je pense que ça pourrait résoudre en partie mon problème parceque de toute façon, actuellement, dès que je crée un thread "Session", je perds sa référence, donc impossible de le tuer proprement.
Ceci dit, le service refuse de s'arrêter même si aucune session n'a démarré donc...

5 réponses

MrDogbert Messages postés 133 Date d'inscription jeudi 26 octobre 2000 Statut Membre Dernière intervention 20 juillet 2004 1
18 juil. 2004 à 13:47
1/ ici c est un forum pour VB. mais bon ...

2/ ta variable "dataRcp" j en aurai fait un StringBuilder plutot qu un String car cela est couteux d instancier sans arret des String (qui sont des chaines de caractères fixes contrairement au StringBuilder)

3/ pour les collection tu dois pouvoir créer ta collection typée en héritant de CollectionBase et tu dois pouvoir rajouter un Enumerator a ta collection pour y accéder par un for each. Si tu hérites de CollectionBase regarde si mybase.list n en possède pas déjà un.

4/ j aurais fait la création des nouveaux thread dans le constructeur des classes Server ou Session ou dans la fonction startServer ou startSession plutot que dans la fonction qui instancie ces classes.

5/ pendant l execution d un thread tu peux faire thread.currentThread pour connaitre le thread qui exécute le code que tu regardes.

6/ Si tu créés le Thread dans la fonction sessionStart par exemple tu peux stocker le thread dans une variable globale de ton application.

7/ lors de l'appel a sessionStop tu peux essayer de faire thread.currentThread.stop par exemple.

8/ ta variable "oServer" dans "Service1" fais en une globale et appelle sa fonction stop() dans OnStop de ton service. tu auras la main sur le thread et sur l objet. là on ne sait pas vraiment ce que devient ton objet. il n est pas forcément détruit ce qui fait qu il n'appellera pas la destruction de tes sessions.

voila. pioches dans ces idées. ce n est pas la sainte bible mais ya petetre quelque chose de pas trop bete dedans.

MRDOGBERT
0
cs_liquide Messages postés 1016 Date d'inscription samedi 22 mars 2003 Statut Membre Dernière intervention 24 juin 2008
18 juil. 2004 à 13:50
je suis sur le site VBfrance et je vois ce post ... c'est étonnant, ca ne ressemble pas a de la programmation VB.

Soit il y a eu un plantage sur les posts, soit tu t'es peut être trompé de site.

Ceci dit, je ne capte rien à ta prog, et pour cause, je ne connais que le basic.

bonne prog
liquide
0
MagicBuzz Messages postés 4 Date d'inscription dimanche 18 juillet 2004 Statut Membre Dernière intervention 19 novembre 2005
18 juil. 2004 à 13:51
Merci pour toutes ces réponses :)

Je regarde ça, et je te dis ce que ça donne :)

PS: Je suis arrivé ici en tapant "www.csharp.com" donc je pensais que c'était un forum c# :(
0
MrDogbert Messages postés 133 Date d'inscription jeudi 26 octobre 2000 Statut Membre Dernière intervention 20 juillet 2004 1
18 juil. 2004 à 18:30
bon alors t es excusé mais fais gaffe! certains membres pourraient te lyncher, ce sont des oufs malades sectaires! attention!!!

non je rigole. envoies un msg a Nix pour signaler le probleme.

MRDOGBERT
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
18 juil. 2004 à 19:00
Salut,

aucun probleme, manque seulement 'fr':
csharpfr.com
J'ai fait une csbar pour naviguer entre les differents sites CS, voir rubrique telechargements a gauche.

ciao...
BruNews, Admin CS, MVP Visual C++
0
Rejoignez-nous