Programovanie služieb vo Windows - 4. diel
Začíname dopĺňať Class Server1
Doplníme konštanty a konštruktory:
public partial class Server1 : Component { private const string DISPLAYNAME = "Moje_Service_1"; private const string PATHFILE = @"c:\Temp\quotes.txt"; private const string THREADNAME = "Listener"; private const string MACHINENAME = "."; //1 private const string LOGNAME = "Application"; //2 private TcpListener listener = null ; private int port = 0 ; private string filename = String.Empty ; private List<string> quotes; private Random random; private Thread listenerThread = null ; private EventLog eventLog1 = new EventLog() ; private byte[] buffer; public Server1() : this (PATHFILE) //3 { } public Server1(string filename) : this(filename, 7890) //3 { } public Server1(string filename, int port) //3 { this.filename = filename; this.port = port; InitializeComponent(); Init(); eventLog1.WriteEntry("Konstruktor ", EventLogEntryType.Information); //0 } public void Start() //4 { ReadQuotes(); //5 eventLog1.WriteEntry("Start ", EventLogEntryType.Information); //0 - testovací smazat listenerThread = new Thread(new ThreadStart(ListenerThread)); //6 listenerThread.IsBackground = true; //7 listenerThread.Name = THREADNAME; //8 listenerThread.Start(); //9 } public void Stop() { listener.Stop(); } public void Suspend() { listener.Stop(); } public void Resume() { Start(); } public void RefreshQuotes() //10 { ReadQuotes(); //5 } protected void ReadQuotes() //11 { quotes = new List<string>(); Stream stream = File.OpenRead(filename); StreamReader streamReader = new StreamReader(stream); string quote; while ((quote = streamReader.ReadLine()) != null) { quotes.Add(quote); } streamReader.Close(); stream.Close(); random = new Random(); } protected string GetRandomQuoteOfTheDay() //12 { int index = random.Next(0, quotes.Count); return quotes[index]; } protected void ListenerThread() //13 { try { listener = new TcpListener(IPAddress.Loopback, port); //14 eventLog1.WriteEntry(IPAddress.Loopback.ToString() + " " + port.ToString(), EventLogEntryType.Information); //0 listener.Start(); //15 Socket clientSocket = null; while (true) //16 { if (!listener.Pending()) //17 { eventLog1.WriteEntry(" Není připojení ", EventLogEntryType.Warning); //0 } else { eventLog1.WriteEntry(" Je připijení ", EventLogEntryType.Information); //0 clientSocket = listener.AcceptSocket(); //18 string message = GetRandomQuoteOfTheDay(); //19 UnicodeEncoding encoder = new UnicodeEncoding(); buffer = encoder.GetBytes(message); clientSocket.Send(buffer, buffer.Length, 0); //20 clientSocket.Close(); //21 } Thread.Sleep(1000); //22 //performanceCounterRequestsTotal.Increment(); //performanceCounterBytesSentTotal.IncrementBy(buffer.Length); //requestsPerSec++; //bytesPerSec += buffer.Length; } } catch (SocketException ex) { string message = "Server selhal ve vlákně Listener: " + ex.Message; eventLog1.WriteEntry(message, EventLogEntryType.Error); } } [HostProtectionAttribute(SecurityAction.LinkDemand, Synchronization = true)] //23 private void Init() { eventLog1.Log = LOGNAME; eventLog1.MachineName = MACHINENAME; eventLog1.Source = DISPLAYNAME; EventLogTraceListener traceListener = new EventLogTraceListener(eventLog1); Trace.Listeners.Add(traceListener); }
Popis
- lokálne PC
- získa alebo nastaví názov protokolu, kde bude čítať alebo zapisovať.
- konštruktory
- štart serveru
- načíta obsah súboru do kolekcie List <string>
- príprava nového vlákna
- na pozadí
- meno vlákna
- štart vlákna
- nové volanie ak je služba úplná, bude vysvetlené neskôr
- načíta do quotes [i] obsah súboru
- vracia náhodný text i-teho Riadky súboru
- výkonná časť servera
- inicializuje novú inštanciu TcpListener (127.0.0.1, port)
- začne spracovávať prichádzajúce požiadavky na pripojenie
- nekonečná slučka
- určuje, či sú požiadavky na pripojenie, čaká na vybavenie, pokiaľ nie je klient pripojený -> false
- prijíma žiadosti o pripojenie, čaká na vybavenie
- číta náhodný riadok textu súboru
- odošle riadok textu na klienta
- zavrie Socket pripojenie a uvoľní priradené zdroje
- čaká 1 sekundu, neskôr môžem čas zmenšiť
- inicializácia logu a trastování
Testujeme
- otvoríme zložku WindowsService1 - bin - inštalačná
- spustíme cmd.exe v režime administrátora
- zadáme príkaz Uninstall.bat a potom Install.bat
- ak inštalácia služby prebehne bez závad, zobrazíme si okno služieb
- spustíme našu službu na 2-5 sekúnd, potom ju zastavíme
- nebudeme vykonávať odinštalovanie služby !! (To znamená Uninstall.bat)
Našu službu sme týmto zaregistrovali v databáze služieb a vykonali zápis do registra.
Nastavíme TestServeru, MujServerEventListener a CLIENTSERVER ako exe projekty. Vykonáme kompiláciu celého nášho projektu.
Pretiahneme z priečinka debug týchto projektov spúšťacie súbory na plochu ako zástupcu. Spustíme CLIENTSERVER, MujServerEventListener a nakoniec TestServeru. Ak všetko funguje, uvidíte:
Vo všetkých projektoch môžete ladiť, krokovať a vykonávať bežné činnosti Visual Studia.
Vytváranie počítadiel pre sledovanie výkonu
Novú kategóriu čítačov pre našu službu vytvoríme v prieskumníkovi serverov, v Visual Studio.
Po vyplnení prihlasovacie tabuľky, ak nie sme administrator, VS našu aplikáciu uloží, automaticky sa prihlási ako administrátor Visual Studia a znovu otvorí našu aplikáciu.
Pravým tlačidlom myši na počítadlách výkonu zadáme novú kategóriu a zobrazí sa tabuľka.
Tabuľku vyplníme podľa našich požiadaviek.
Pridávanie komponentov PerformanceCounter do služby
Môžeme postupovať buď pretiahnutím komponenty alebo pridávať z panela nástrojov. Zase najjednoduchší spôsob je pretiahnuť komponent z prieskumníka serverov. Týmto spôsobom dôjde k automatickému nakonfigurovanie nových inštancií:
- meno PC (MachineName)
- názov kategórie (categoryname)
- vlastnosť názvu (CounterName)
Nastavíme performanceCounter.ReadOnly = false, v tejto aplikácii služby nebudeme počítadlá výkonu čítať, ale iba zapisovať.
Výkonnostný počítadlá, ktoré ukazujú celkovej hodnoty, zvyšujeme priamo v metóde ListenerThread () triedy môjserver (pozri ukážka kódu). Pre počítanie celkového počtu požiadaviek použijeme metódu performanceCounter.Increment () a výpočet odoslaných bajtov možno vykonať volaním metódy performanceCounter.IncrementBy ()
Ospravedlňujem sa, obrázky sú z inej služby a už som ich nepředělával.
Class Server1 - doplnenie kódu
public partial class Server1 : Component { //původní kód private byte[] buffer; private int bytesPerSec = 0; private int requestsPerSec = 0; protected void ListenerThread() { //původní kód if (!listener.Pending()) { Thread.Sleep(500); } else { //původní kód //čítače výkonu this.performanceCounter1.Increment(); requestsPerSec++; bytesPerSec += buffer.Length; } private void Init() { //přidáme this.performanceCounter1.ReadOnly = false; this.performanceCounter2.ReadOnly = false; this.performanceCounter3.ReadOnly = false; } private void timer1_Tick(object sender, EventArgs e) { this.performanceCounter2.RawValue = requestsPerSec; this.performanceCounter3.RawValue = bytesPerSec; bytesPerSec = 0 ; requestsPerSec = 0; } }
Aby všetko fungovalo tak ako má, musíme pretiahnuť na plochu čítač (Timer1), dĺžka intervalu 1000 mS a trvalo spúšťaný. Myslím, že táto časť nepotrebuje komentár. Problém môže nastať v nevhodne zvolenom type počítadlá výkonu, tu dopĺňam článkom z CodeProject:
Riešenie nie je úplné, po reštarte alebo odinštalovanie sa z prieskumníka severu stratí naše aplikácie z počítadiel výkonu. Ak naozaj počítadlá výkonu potrebujete, musíte vytvoriť kolekciu, v tomto prípade MojeService1. Akým spôsobom to urobíte je rozobraté v uvedenom článku. Pokladám tento opis za zbytočný, článok by sa rozšíril o dva ďalšie diely. Počítadlá výkonu musí byť taktiež registrované v registri.
Budeme pokračovať v ďalšom dieli.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 76x (326.73 kB)
Aplikácia je vrátane zdrojových kódov v jazyku C#