Où trouver des tutos ? [C#] - C#/.NET managed - Programmation
Marsh Posté le 17-07-2004 à 05:59:48
y a pas mal de sources assez simples sur csharpfr.com.
Sinon tu peux trouver des cours de c# sur le site du labo .net de supinfo, je sais qu'il y a notament une vidéo qui montre comment faire un service avec Visual.
Marsh Posté le 17-07-2004 à 12:02:11
Salut, je viens de trouver en effet les cours sur le site labo-donet, merci, je n'avais pas eu l'idée de voir de ca côté. (faut dire que la dernière fois que j'y étais allé, c'était plus orienté outils réseaux de Windows que .NET
Marsh Posté le 17-07-2004 à 18:51:13
Pour le service et les connections assynchrones c'est ok.
Par contre, j'ai pas trouvé comment faire un pool de connections
Il faut absolument que mon programme accepte un nombre "infini" de connections, sinon c'est mort
Marsh Posté le 17-07-2004 à 19:15:12
créer un thread pour chaque connexion entrante ça convient pas ?
Marsh Posté le 17-07-2004 à 19:38:08
le bon vieux select() est dispo en .NET: System.Net.Sockets.Socket.select()
je rappelle qu'il sert à gérer les IOS sur n sockets dans un seul thread.
vers la msdn
Marsh Posté le 17-07-2004 à 21:19:42
Bon, des nouvelles du front.
J'ai détruit mon ancien code (qui marchait bien pourtant), un programme en mode console avec une connexion simple.
A la place, j'ai créé un service windows tel qu'indiqué dans la vidéo sur supinfo. L'install a merdé, mais en bourrinant bien, j'ai fini par pouvoir l'installer.
Pour ce qui est du code à propos du cours sur les sockets...
Déjà, il est truffé de bugs. J'ai passé deux heures à essayer de savoir quel nom correspondait à quel hypothétique variable.
Ce que j'ai écrit compile, mais je doute que ça marche, et surtout, je ne vois pas trop ce que c'est censé pouvoir faire (à priori, ça devrait polluer mon eventlog et recopier tout ce que le serveur reçoit dedans. Pas terrible mais bon )
Seulement, je ne sais pas si c'est parceque c'est encore plus buggé que je ne l'imaginais, ou si c'est parceque je ne sais pas coder un webservice (ce qui est sûr), mais autant il démarre et s'arrête comme je lui demande sans planter, autant un telnet sur ma bécane reste muet.
Si une personne pouvait déjà me confirmer que mon service est censé "fonctionner"... Ca me permettrait de me concentrer sur ma class cSocket qui doit merder à plein tube...
Voici mon code (attention les mirettes, prenez une bassine au cas où vous auriez subitement des remontées gastriques) :
Service1.cs
Code :
|
socket.cs :
Code :
|
Marsh Posté le 17-07-2004 à 21:29:12
Ha si en fait ça tourne (pas fait exprès DU TOUT )
Par contre heu...
J'ai une exception qui atterri dans l'eventlog lors de l'appel de la ligne :
s.Listen(100);
Message :
Error: System.Net.Sockets.SocketException: Un argument non valide a été fourni
at System.Net.Sockets.Socket.Listen(Int32 backlog)
at MagicMUD.cSocket.StartListening()
C'est quoi le problème
Marsh Posté le 17-07-2004 à 22:03:14
J'éai viré le s, et j'ai utilisé mon socket "lintener" à la place (parceque je comprends pas pourquoi ils font référence à ce "s", surtout qu'il n'est marqué que là dans le cours.
Maintenant, il n'accepte jamais les connections (le listen passe bien, mais dans la boucle "while (true)" mais ne rentre jamais dans le "listener.BeginAccept(new AsyncCallback(acceptCallBack), listener);"
Je ne sais pas à quoi c'est dû. En tout cas un telnet sur le service retourne une erreur comme quoi il est impossible de se connecter. Le service quand à lui reste stoïque dans sa bêtise, et ne plante pas ni ne lève la moindre erreur. Il reste juste bloqué là.
Ca me lourde bien... J'ai quand même passé la journée sur cette connerie, et vu que je suis perduadé que de toute façon ce code ne me sert à rien (faute de trouver mieu) le temps que je passe à trouver pourquoi ça merde ne me servira de toute façon à rien...
Corriger un code imbitable (car plus que mal expliqué dans le cours "l'exemple par de lui-même" => Biensûr oui je vois ça, Supinfo c'est pas pour moi ça c'est clair !) ne m'apporte rien quant à la compréhensio du fonctionnement des Sockets en mode asychrone, et à par me démotiver, je ne vois pas ce que ça pourrais faire...
Bon, sinon, j'ai réfléchit un peu (bah ouais ça m'arrive des fois).
Et je me demande... Je doute fortement que les sockets asychones me soit de la moindre utilité au final...
Tout ce que je veux, moi, c'est d'avoir un thread par connection. Après, du moment que ce thread envoie à la routine principale les informations reçues, ça ne me sert à rien de plus.
Quoique... Nan, si, ça m'est utile... Il faut que j'envoie au client telnet (donc via la connection) les modifications de son environement, donc je ne peux pas me contenter d'attendre comme un con qu'il fasse une action pour lui afficher qu'un mob est en train de l'attaquer en fait...
Pffff... Un coup de main serait vraiment le bienvenu
Marsh Posté le 17-07-2004 à 22:26:39
c'est pas très dur tout ça.
ton expertise en dev ouaibe ne t'aidera pas là. Prends donc les choses humblement en partant du principe que t'es un newbie. Essaye juste dans un main() d'ouvrir une socket en écoute, puis teste avec telnet quand tu y sera parvenu. Après complexifie ton truc, ça va venir tout seul.
Marsh Posté le 17-07-2004 à 22:34:42
Ca ca marche.
J'ai déjà fait des premiers tests avec une connection synchrone, et j'obtenais parfaitment ce que je voulais.
Seulement, moi j'ai besoin d'avoir une connection assynchrone afin de pouvoir envoyer des choses au client sans attendre d'action de sa part (si c'est bien ce que j'ai compris du mode synchorone) et surtout, j'ai besoin que plusieurs personnes se connectent à la fois, seulement j'ai trouvé nul part comment faire un pool de connection.
J'ai regardé l'instruction select, je vois ce qu'elle fait, mais je ne suis pas sûr qu'elle réponde à mon besoin. Une fois établie, la connection ne se ferme que lorsque l'utilisateur quite l'appli (contraîrement à un serveur HTTP par exemple qui se déconnecte aussitôt qu'il a chargé une page). Donc je n'ai pas le souci de réutiliser les sockets, mais il faut bien que j'en ai un par utilisateur connecté. Je compte mettre tout ce monde là dans des threads isolés (connection + infos sur le joueur)
Marsh Posté le 17-07-2004 à 22:41:20
bon bien tu va devoir avoir un thread acceptant les demandes de connections entrantes, avec une "socket serveur". Cette socket serveur peut accepter n connections à la suite en bouclant autour de l'appel accept().
Ensuite, tu va avoir n thread pour écouter les n clients ayant chacun leur propre connection tcp/ip.
Les connectections tcp/ip sont full duplex, tu peux envoyer et recevoir dessus en même temps. Donc il n'y a pas de pb pour avoir un autre thread gérant la maj des infos clients ("les mecs en telnet" ).
Marsh Posté le 17-07-2004 à 22:45:57
ha bon ? ok, donc si j'ai plus d'assynchrone à gérer du côté de la connection, ça va être tout à coup bien plus facile
Merci pour ces infos.
Je vais donc me pencher sur les threads pour mieu en comprendre le fonctionnement.
Marsh Posté le 17-07-2004 à 22:51:22
Il est possible de gérer tout avec un seul thread, en utilisant une boucle principale d'application, architecturée autour de l'appel à select().
Menfin la solution avec threads fait plus moderne, et gère automatiquement le load balacing dans le cas ou les traitements pour un client particulier prennent beaucoup de temps (ce qui évite de bloquer les autres...)
Marsh Posté le 17-07-2004 à 23:12:22
Et surtout je vais faire tourner l'appli sur un bi-pro, donc il vaut mieu au moins deux threads pour en tirer parti
Marsh Posté le 17-07-2004 à 23:15:47
je doute que ce soit le cpu qui limite ton petit serveur de jeu , mais dans l'esprit tu as raison
Marsh Posté le 17-07-2004 à 23:44:16
Ca peut rapidement dépendre.
Si j'ai le courrage d'aller jusqu'au bout (ça y'a rien de moins sûr, je viens une fois de plus de repartir de 0 parceque j'arrive a rien avec les threads) je compte faire fonctionner les mobs à la façon tamagoshi (ils auront leur propre vie, et agiront de leur propre chefs, comme les joueurs - achats/vente d'items, attaque d'autres mobs, gains d'xp, etc.) Ceci pourrait rapidement bouffer pas mal de CPU...
Mais bon, pour le moment c'est d'arriver à faire une saleté de routine à la noix qui veuille bien accepter deux connection telnet et ne pas les confondre
Marsh Posté le 18-07-2004 à 00:11:36
Bon, là j'ai un peu de mal avec la logique des Services.
J'ai trouvé cet exemple de thread :
http://msdn.microsoft.com/library/ [...] torial.asp
Enfin un truc facile à comprendre.
Maintenant, dans mon Service, j'ai 3 méthodes par défaut :
OnStart()
Main()
OnStop()
D'après des traces, les trois procédures sont lancées (en toute logique) dans cet ordre. Le OnStop() ne le lançant que lorsque j'arrête le service.
Donc...
Le but du jeu, c'est de spliter l'exemple de façon à :
-> Lancer le thread dans le OnStart()
-> Arrêter le thread dans le OnEnd()
-> Et dans le main... Ben pas faire grand chose pour le moment.
Seulement, lorsque je mets mes objets oThread et oAplha en global, j'ai une erreur "machin denote a Field where a Class was expected"
Pas moyen de me défaire de cette erreur.
Comment faire ?
Je veux bien tout mettre dans le Main, du moins pour le OnStart() c'est pas gênant.
Mais à ce moment, comment le thread va-t-il être arrêté ? Il ne faut pas que je l'arrête tant que le service tourne... Donc je n'ai pas d'autre solution que de ne pas le tuer... Et compter sur le garbage collector pour le faire lorsque le service s'arrête
Y'a pas plus propre ???
Marsh Posté le 18-07-2004 à 00:39:01
Bon, j'ai shooté me main, et ça marche (faut pas chercher à comprendre)
En fait, le main se lance au moment du stop, je sais pas à quoi il sert, sur la MSDN il n'est spécifié nul part...
Marsh Posté le 18-07-2004 à 11:14:47
YES ! Ca marche
Alors, j'utilise ça :
-> Dans le OnStart du service, je démarre un thread qui lance le socket d'écoute.
-> Dans le thread, je boucle sur socket.Accept()
-> Pour chaque "session" créé par le Accept(), je lance un nouveau thread qui va se charger de communiquer avec le client.
Tout marche bien, j'ai mon service qui démarre, je peux me connecter à deux dessus, et ca marche
Par contre, depuis que j'ai mis du Socket dans mon service, je ne peux plus arrêter le service
Faut que je fasse un "end task" dessus à chaque fois
La méthode "Abort()" d'un thread, elle fait quoi au juste ?
Chaque Thread tourne sur un objet à lui, j'ai donc bien mis les destructeurs. Mais à priori c'est pas le destructeur de l'objet qui est lancé (c'est assez logique, puisqu'un thread porte sur une fonction, pas sur un objet)
Bref... Comment je shoot tout ça ?
Voilà des extraits de mon code, histoire que ce soit plus clair :
Service1.cs:
Code :
|
Server.cs:
Code :
|
En fait, qu'il y ait eu une connection ou non au service, ca reste bloqué. Je pense donc c'est c'est au niveau du Accept() que ça coince.
Quand j'avais un exemple bête de Thread (sans socket), ça marchait. En effet, j'avais un thread qui faisait une boucle infinie, mais pourtant que je faisais Abort() dessus il s'arrêtait gentillement
Marsh Posté le 18-07-2004 à 12:05:08
Sinon, depuis le thread Server qui crée les thread Session, je voudrais stocker des références vers chaque thread Session, afin de pouvoir les retrouver facilement (histoire d'envoyer par exemple les notification de déplacement des autres joueurs)
Comment faire ? J'ai pensé à un tableau, mais il va rapidement y avoir des trous. Deplus, je ne sais pas si redimensionner un tableau à chaque nouvelle/fin de session est très heureux comme solution.
Y'a quoi comme objet qui pourrait faire ça ? Une sorte de collection que je pourrais atteindre avec "foreach" et ajouter/supprimer des éléments avec add() et delete()
Merci de votre aide
Marsh Posté le 18-07-2004 à 12:25:07
Vous connaissez pas un forum C# avec des gens qui répondent ?
Merci quand même pour ceux qui m'ont répondu hein, je ne dénigre pas ce forum. Mais disons que les gens qui connaissent le C# ici ne sont pas très nombreux, et peu d'entre eux daignent me répondre (ou alors ne savent pas, je ne sais pas) et du coup je reste bloqué comme un con sur des conneries.
Oui, je sais, il faut aussi que je m'achète un bouquin.
Marsh Posté le 18-07-2004 à 14:41:23
Désolé de pas pouvoir t'aider. J'ai jamais manipuler de thread/pool sous .Net.
Ce forum est plutot basé sur les open sources j'ai remarqué.
T'as essayé le forum du labo dotnet de supinfo (ki t'as été donné + haut) ou encore le forum de développez.com ?
C'est là où j'me tourné généralement pour des dév en .Net.
Marsh Posté le 18-07-2004 à 15:02:30
Sur le site de supinfo, j'ai essayé, mais aucune réponse.
Je suis allé sur csharp.com et j'ai posté sur leur forum.
J'ai eu des réponses (qui m'aident énormément, maintenant mon service s'arrête !)
Mais c'est un forum vb en fait, donc je vais pas continuer à poster dessus.
Là, j'ai un problème.
J'ai un objet global que j'instancie dans la fonction "OnStart".
Son desctructeur n'est jamais appelé, même lorsque j'arrête le service.
Dans le OnStop, j'ai essayé monObj = null; mais c'est sans effet. Comment détruire un objet ? (et donc forcer le destructeur à s'éxécuter avant que le GC ne le tue à la bourrin)
Je vais faire un tous sur developpez.com Mais de mémoire, je n'ai jamais eu de réponse là-bas
Marsh Posté le 18-07-2004 à 15:27:29
En fait, j'ai cette class par exemple :
Code :
|
Lorsque j'appelle puis détruit un objet de ma class :
Code :
|
=> Dans l'eventlog, j'ai bien "Création d'une nouvelle session"
Si un client telnet se conencte, j'ai bien aussi "J'ai reçu ça : ..."
=> Mais je n'ai jamais "Terminaisaon d'une session"
Actuellement, ca me prose un gros problème, parceque lorsque j'arrête mon service, tous les clients telnet restent connectés, ce qui prouve que j'ai une chiée de threads qui tournent encore car il n'ont été détruits ni par le destructeur, ni par le GC
Marsh Posté le 18-07-2004 à 16:43:24
On ne détruit pas un objet comme ça :monObj = null
légère explication sur les destructeurs en c# sur le site d'en bas:
http://www.zdnet.fr/builder/archit [...] 213,00.htm
Ou bien tu fais à la façon c++ ( ~Class ) qui équivaut aussi à "Finalize" en c#.
Marsh Posté le 18-07-2004 à 16:47:19
Quand j'appelle le Finalize() depuis une méthode "dispose" comme dans l'article MSDN, j'ai une erreur de compilation ma disant que je n'ai pas le droit de l'appeler directement
Marsh Posté le 18-07-2004 à 16:59:19
j'sais pas si ça peut résoudre ton problème :
http://www.c-sharpcorner.com/Code/ [...] harpNS.asp
Marsh Posté le 18-07-2004 à 17:55:49
c'est tout des articles que j'ai déjà lu
nan, y'a pas moyen, mes destructeurs ne sont jamais appelés.
tant pis, je laisse tomber, car même en reprenant un exemple basic avec une class simplissime, le destructeur ne se lance pas. Doit y avoir un truc au niveau du service qui fait qu'il ne passe par par le GC ou autre...
en tout cas, j'ai remarqué que dans le OnStop() de toute façon les objets ne sont plus visibles (ils tournent encore mais impossible de les atteindre)
puis les objets meurrent tous seuls au bout d'une dizaine de secondes.
on va dire que c'est très bien comme ça
Marsh Posté le 17-07-2004 à 02:30:10
Ouais, je sais, google, mais je suis pas doué : soit je tombe sur des tutos super complexes, soit des trucs tellement basics que j'avance pas... Soit je trouve rien.
En gros, j'aimerais savoir comment faire :
- Un service
- Un pool de connection socket
- Plusieurs threads (pour le pool de ocnnections surtout)
En fait, je voudrais écrire un petit MUD tout simple. Pour ceux qui ne connaissent pas, il s'agit d'un type de jeu de rôle via telnet.
Le but serait de le faire tourner en tant que service, et pour le moment, simplement accepter plusieurs connections à la fois, et les faire inter-agir avec la routine principale.
Je suppose donc, pour le pool de connections, qu'il faut que je crée un thread qui écoute sur un port, et à chaque nouvelle connection, qu'il relance une nouvelle instance de lui-même, via une demande au process principal. J'ai bon ?
Pour le moment c'est super, j'ai trouvé un tuto pour faire un serveur qui répond a un port, quand je me connecte via telnet il me répond ce que je tape, c'est super Mais je vais pas aller loin avec ça