OwnzYa
Messages postés6Date d'inscriptionsamedi 27 mars 2010StatutMembreDernière intervention17 février 2013
-
13 févr. 2013 à 14:47
OwnzYa
Messages postés6Date d'inscriptionsamedi 27 mars 2010StatutMembreDernière intervention17 février 2013
-
17 févr. 2013 à 08:59
Bonjour à tous,
après je ne sais combien d'heures de codage sur un programme de jeu développé en c# qui accueil tous les jours environ 1000/1500 utilisateurs, j'ai pu constater que cela ramait beaucoup.
Je tiens à préciser que ce qu'est sensé être le jeu tournant sur cet émulateur ne regarde personne et que les commentaires démesurés ne seront pas les bienvenus (je fais référence à un forum qui a fait des commentaires inutiles et très désagréable dont je ne citerai pas le nom, disant je ne sais trop quoi n'étant pas en rapport avec le problème à suivre). Ce n'est pas un émulateur prévu pour pirater quoi que ce soit, ni pour faire exploser l'univers.
Je m'explique :
moi et mon équipe avons développé un émulateur pour un jeu, un serveur quoi, et nous souhaitons gérer la modération des propos des utilisateurs et toute la gestion du jeu via des serveurs irc.
Lorsqu'un utilisateur se connecte au jeu, il est sans le savoir par le biais de l'émulateur (qui ouvre une socket pour l'utilisateur) connecté également sur un serveur irc (UnrealIRCd). C'est grâce à ça que sont publiés les nombreux propos des utilisateurs sur des salons privés du serveur IRC. Nous les modérons en les kickant, bannissant du serveur IRC ce qui provoque le même effet sur le jeu.
Sauf que, hier en officialisant cette fonction, au bout d'un certain nombre de connectés au jeu et donc d'un certain nombre de sockets ouvertes par le programme en c# (l'émulateur) je me suis aperçu que cela laguait énormément voire que le jeu devenait impossible à accéder.
Il est possible que ça vienne du "Threading". Voici la page concernée :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections;
using System.Text;
using System.Net.Sockets;
using System.IO;
using System.Threading.Tasks;
using System.Threading;
using Butterfly.userHotel.GameClients;
using Butterfly.userHotel.Rooms;
using Butterfly.userHotel.Navigators;
using Butterfly.userHotel.Rooms.RoomIvokedItems;
using Butterfly.userHotel.ChatMessageStorage;
using Butterfly.Core;
using Butterfly.Messages;
using userEvents;
using Database_Manager.Database.Session_Details.Interfaces;
using Uber.userHotel.Rooms;
namespace Butterfly.IRC
{
struct IRCConfig
{
public uint userID;
public string server;
public int port;
public string nick;
public string name;
public int channel;
public bool isarealBot;
public void AddAccess(string nick)
{
using (IQueryAdapter dbClient = ButterflyEnvironment.GetDatabaseManager().getQueryreactor())
{
dbClient.runFastQuery("INSERT INTO access (allow) VALUES('" + nick + "')");
}
}
public void DelAccess(string nick)
{
if (nick.Contains("[absent]")) { nick = nick.Replace("[absent]", ""); }
if (nick.Contains("[absente]")) { nick = nick.Replace("[absente]", ""); }
if (nick.Contains("[occupe]")) { nick = nick.Replace("[occupe]", ""); }
if (nick.Contains("[occupee]")) { nick = nick.Replace("[occupee]", ""); }
using (IQueryAdapter dbClient = ButterflyEnvironment.GetDatabaseManager().getQueryreactor())
{
dbClient.runFastQuery("DELETE FROM access WHERE `allow` = '" + nick + "'");
}
try
{
ButterflyEnvironment.GetGame().GetClientManager().GetClientByUsername(nick).Disconnect();
}
catch
{ }
}
userHotel.Users.user user = ButterflyEnvironment.getuserForName(target);
if (user != null)
{
if (!user.GetBadgeComponent().HasBadge(badge))
{
user.GetBadgeComponent().GiveBadge(ButterflyEnvironment.FilterInjectionChars(badge), true);
sendData("NOTICE", trigger + " Le badge a bien été ajouté.");
}
else { sendData("NOTICE", trigger + " Cet utilisateur a déjà ce badge."); }
}
userHotel.Users.user user = ButterflyEnvironment.getuserForName(target);
uint userid = user.Id;
using (IQueryAdapter dbClient = ButterflyEnvironment.GetDatabaseManager().getQueryreactor())
{
dbClient.runFastQuery("DELETE FROM user_badges WHERE `user_id` '" + userid + "' AND `badge_id` '" + badge + "'");
sendData("NOTICE", trigger + " Le badge a bien été retiré.");
}
}
}
}
/*
* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
* USER
* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
*/
else
{
/*
* DETECTION DE LA REPONSE DE BIENVENUE DE L'IRCD
*/
if (ex[1] == "001")
{
GameClient user = ButterflyEnvironment.GetGame().GetClientManager().GetClientByUserID(config.userID);
sendData("JOIN", "#monitori_" + config.channel);
sendData("PRIVMSG", "#monitori_" + config.channel + " New connection");
sendData("AWAY", user.Getuser().Motto);
}
/*
* DETECTION D'UN PRIVMSG
*
*
*/
if (ex[1] == "PRIVMSG")
{
}
/*
* DETECTION DU RAW 404
* Dans le cas où l'utilisateur reçois ce message, c'est qu'il est ban quiet du salon où il se trouve
* Ce qui correspond à un "mute" sur l'hôtel.
* On procède alors à une vérification : si le user n'est est encore mute, on execute la commande demute.
*/
if (ex[1] == "404")
{
GameClient user = ButterflyEnvironment.GetGame().GetClientManager().GetClientByUserID(config.userID);
if (!user.Getuser().Muted)
{
user.Getuser().Muted = true;
}
}
/*
* DETECTION DU MODE +b ~q:
* Dans le cas où l'utilisateur reçois ce message, c'est qu'il est ban quiet du salon où il se trouve
* Ce qui correspond à un "silence" sur l'hôtel.
* On procède alors à une vérification : si le user n'est pas encore mute, on execute la commande de mute.
*/
if (ex[1] == "MODE" && ex[2].IndexOf("#") != -1 && ex[3].Contains("+b"))
{
if (data.Contains("~q:" + config.nick))
{
GameClient user = ButterflyEnvironment.GetGame().GetClientManager().GetClientByUserID(config.userID);
if (!user.Getuser().Muted)
{
user.Getuser().Muted = true;
}
if (user.Getuser().CurrentRoomId != 0)
{
Room Room = ButterflyEnvironment.GetGame().GetRoomManager().GetRoom(user.Getuser().CurrentRoomId);
Room.AddBan(user.Getuser().Id);
Room.GetRoomUserManager().RemoveUserFromRoom(user, true, false);
}
}
}
if (ex[1] == "MODE" && ex[2].IndexOf("#") != -1 && ex[3].Contains("-b"))
{
if (data.Contains("~q:" + config.nick))
{
GameClient user = ButterflyEnvironment.GetGame().GetClientManager().GetClientByUserID(config.userID);
if (user.Getuser().Muted)
{
user.Getuser().Muted = false;
}
}
}
/*
* DETECTION DU MODE +m
* Dans le cas où l'utilisateur reçois ce message, c'est qu'il est mute du salon où il se trouve.
* Ce qui correspond à une maintenance "silence" sur l'hôtel.
* On procède alors à une vérification : si le user n'est pas encore mute, on execute la commande de mute.
*/
if (ex[1] == "MODE" && ex[2].IndexOf("#") != -1 && ex[3].Contains("+m"))
{
GameClient user = ButterflyEnvironment.GetGame().GetClientManager().GetClientByUserID(config.userID);
if (!user.Getuser().Muted)
{
user.Getuser().Muted = true;
}
}
if (ex[1] == "MODE" && ex[2].IndexOf("#") != -1 && ex[3].Contains("-m"))
{
GameClient user = ButterflyEnvironment.GetGame().GetClientManager().GetClientByUserID(config.userID);
if (user.Getuser().Muted)
{
user.Getuser().Muted = false;
}
}
/*
* DETECTION DU MODE +e
* Dans le cas où l'utilisateur reçois ce message, c'est qu'il est dans la liste des excpetions du salon où il se trouve
* Ce qui correspond à un "bloque d'appart" sur l'hôtel.
* On procède alors à une vérification : le user est bloqué de l'appart où il est, on execute la commande de bloquage.
*/
if (ex[1] == "MODE" && ex[2].IndexOf("#") != -1 && ex[3].Contains("+e") && ex[4].Contains(config.nick))
{
GameClient user = ButterflyEnvironment.GetGame().GetClientManager().GetClientByUserID(config.userID);
if (user.Getuser().CurrentRoomId != 0)
{
Room Room = ButterflyEnvironment.GetGame().GetRoomManager().GetRoom(user.Getuser().CurrentRoomId);
Room.AddBan(user.Getuser().Id);
Room.GetRoomUserManager().RemoveUserFromRoom(user, true, false);
}
}
/*
* DETECTION DU KICK
* On cherche à savoir si le kick est destiné à l'utilisateur actif. Si c'est le cas :
* On envoit un message indiquant à l'utilisateur le motif de l'exclusion du salon (qui le kickera donc de l'appart où il est)
*/
if (ex[1] == "KICK" && ex[3] == config.nick)
{
string desc = ex[4].Substring(1);
GameClient user = ButterflyEnvironment.GetGame().GetClientManager().GetClientByUserID(config.userID);
sendData("JOIN", ex[2]);
if (user.Getuser().CurrentRoomId != 0)
{
user.Getuser().CurrentRoom.GetRoomUserManager().RemoveUserFromRoom(user, true, false);
user.SendNotif("Tu as été kické(e) de l'appart par un modérateur (" + desc + ")");
}
else
{
user.SendNotif("Ceci est un avertissement de la part d'un modérateur (" + desc + ")");
}
}
/*
* DETECTION D'UNE NOTICE
* Lors de la détection d'une notice, si elle n'est pas une notice d'identification et qu'elle ne provient pas du serveur,
* elle est alors affiché comme message "important" sur le client de l'utilisateur concerné.
*/
if (ex[1] == "NOTICE" && ex[2] != "AUTH" && !ex[0].Contains("userbeta.co"))
{
try
{
// Return content
string content = ex[3].Substring(1) + " " + ex[4];
// Execute command on hotel
GameClient user = ButterflyEnvironment.GetGame().GetClientManager().GetClientByUserID(config.userID);
user.SendBroadcastMessage(content);
}
catch
{
break;
}
}
/*
* DETECTION D'UN KILL
* Si un kill intervient sur le pseudo irc de l'utilisateur, il est automatiquement déconnecté de l'hôtel
* Il en va de même pour tout les messages d'erreur provenant de l'ircd, pouvant entrainer la déconnexion de l'utilisateur du
* serveur irc, empêchant ainsi tout traitement des messages irc sur le client de l'utilisateur, il devra donc se reconnecter.
*/
if (ex[0].Contains("ERROR"))
{
ButterflyEnvironment.GetGame().GetClientManager().GetClientByUserID(config.userID).Disconnect();
}
}
}
}
public void SayMessage(string msg, bool Shout, bool Whisper, int channel)
{
// PRIVMSG #salon :Message
// byte[] utf8Bytes = Encoding.UTF8.GetBytes(msg);
yann_lo_san
Messages postés1137Date d'inscriptionlundi 17 novembre 2003StatutMembreDernière intervention23 janvier 201626 13 févr. 2013 à 22:43
Salut,
question :
qui appelle la méthode "Destroy" qui provoque l'arret du thread ?
et de quelle partie du code ?
J'imagine que c'est la classe allouant les "IRCBot"...
La fonction IRCThread.Abort() dans "Destroy" provoque 2 fois le ThreadAbordException (a la fin du catch de CallbackThread)
du coup il se peut que le finally ne soit jamais exécuté, a tracer.
As-tu vérifié que le nombre de thread "alive" n'était pas énormément supérieur au nombre d'utilisateurs effectivement connecté ?
OwnzYa
Messages postés6Date d'inscriptionsamedi 27 mars 2010StatutMembreDernière intervention17 février 2013 14 févr. 2013 à 04:54
Bonjour et merci beaucoup d'avoir répondu,
je suis débutant en c# et je ne connais pas grand chose mise à part ce qu'il y a dans la page de code ci-dessus.
Au niveau du Thread, je ne suis pas encore très bien initié, donc pardonnez-moi si cela ne répond pas à votre question.
La méthode Destroy() est appelé dans une page de code qui s'execute à chaque connexion d'un client à l'emulateur.
yann_lo_san
Messages postés1137Date d'inscriptionlundi 17 novembre 2003StatutMembreDernière intervention23 janvier 201626 14 févr. 2013 à 21:55
Re,
Tu peux toujours essayer ces 2 modif. (si possible bien sur) afin d'éviter la double exception interne (ThreadAbordException) et de laisser le nettoyage de la mémoire au framework.
1 : Enlever la ligne suivante de la méthode destroy : GC.SuppressFinalize(IRCThread);
2 : Ajouter un bloc catch afin de demander la suppression du renvoi d'exception.
public void CallbackThread()
{
try
{
sendData("USER", config.name);
sendData("NICK", config.nick);
//Lets go funny raws
IRCWork();
}
catch (ThreadAbortException)
{
Thread.ResetAbort();
}
catch (Exception exc)
{
//Logging.WriteLine("Communication error : " + exc.MEssage);
}
finally
{
if (sr != null)
sr.Close();
if (sw != null)
sw.Close();
if (ns != null)
ns.Close();
if (IRCConnection != null)
IRCConnection.Close();
}
}
OwnzYa
Messages postés6Date d'inscriptionsamedi 27 mars 2010StatutMembreDernière intervention17 février 2013 17 févr. 2013 à 08:59
Merci de ton aide, ça a l'air de fonctionner mais quelqu'un continue de me dire que "1000 Threads c'est beaucoup trop quand même et que ça va tout faire buguer"...