CKroencke Geschrieben 29. November 2011 Geschrieben 29. November 2011 Guten Tag Community! Ich habe über den allwissenden Freund Google.de ein MSDN Tutorial von Microsoft zum Thema Netzwerkprogrammierung in C# gefunden und gelesen (klickmich). Das funktioniert sehr sehr gut. Jetzt habe ich mir gedacht, erweiterst du das erstmal so, das sich das CD-Laufwerk auf den Clients öffnen lässt und bin auf diesen Programmcode gestoßen: using System.Runtime.InteropServices; [DllImport("winmm.dll")] static extern Int32 mciSendString(string Befehl, string buffer, int bufferSize, IntPtr hwndCallback); Öffnen: mciSendString("set CDAudio door open", null, 127, (IntPtr)0); Schließen: mciSendString("set CDAudio door closed", null, 127, (IntPtr)0); Das wiederrum funktioniert auch gut. Kommen wir nun zu dem Problem. Ich möchte nun, wenn ich bei dem Server (Konsole) sage ich mal "cdopen" eingebe, dieser das an alle Clients schickt und auf jedem Client wird dann eine entsprechende Methode ausgeführt. Da ich aber mit 2 Klassen (Server & ServerThread) arbeite, weiß ich nicht wie ich an den OutputStream gelangen soll, während ich in der Konsole Tastatureingaben machen kann (hier mal meine Klassen) Server: using System; using System.Collections.Generic; using System.Text; using System.Net.Sockets; using System.IO; using System.Collections; using System.Threading; using System.Runtime.InteropServices; namespace ClientServerV2.Server{ public class Server{ private int _port = 0; //Listener initialisieren TcpListener listener = null; // Die Liste der laufenden Server-Threads ArrayList serverThreads = new ArrayList(); //Standard Konstruktor public Server(int port){ _port = port; start(); } public void start(){ // Listener initialisieren und starten listener = new TcpListener(_port); listener.Start(); // Haupt-Server thread initialisieren und starten Thread mainThread = new Thread(new ThreadStart(Run)); mainThread.Start(); // Benutzerbefehle entgegennehmen String strCmd = ""; while(!strCmd.ToLower().Equals("stop")) { strCmd = Console.ReadLine(); if (!strCmd.ToLower().Equals("stop")) { Console.WriteLine("Unbekannter Befehl: " + strCmd); } } // Haupt-Server-Thread stoppen mainThread.Abort(); // Alle Server-Threads stoppen for (IEnumerator e = serverThreads.GetEnumerator(); e.MoveNext(); ) { // Nächsten Server-Thread holen ServerThread st = (ServerThread)e.Current; //und stoppen st.stop = true; while (st.running) { Thread.Sleep(1000); } } // Listener Stoppen listener.Stop(); } // Haupthread des Servers // Nimmt die Verbindungswünsche von Clients entgegen // und startet die Server-Threads für die Clients public void Run() { while (true) { // Warten bis ein Client eine verbindung wünscht TcpClient c = listener.AcceptTcpClient(); // Initialisiert und startet einen Server-Thread // und fügt ihn zur Liste der Server-Threads hinzu serverThreads.Add(new ServerThread(c)); } } } class start { public static void Main() { Server s = new Server(4711); } } } ServerThread: using System; using System.Collections.Generic; using System.Text; using System.Net.Sockets; using System.Threading; using System.IO; using System.Runtime.InteropServices; namespace ClientServerV2.Server { class ServerThread { //Stop Flag public bool stop = false; // Flag für Thread läuft public bool running = false; // Die Verbindung zum Client TcpClient _connection = null; [DllImport("winmm.dll")] static extern Int32 mciSendString(string Befehl, string buffer, int bufferSize, IntPtr hwndCallback); public ServerThread(TcpClient connection) { // Speichert die Verbindung zu dem Client // um diese Später zu schließen _connection = connection; new Thread(new ThreadStart(Run)).Start(); } // Der eigentliche Thread public void Run() { // Flag setzen für "Thread Läuft" this.running = true; // Hole den Stream fürs schreiben Stream outStream = _connection.GetStream(); String strBuf = null; bool loop = true; while (loop) { try { // Hole die aktuelle Zeit als String String strTime = DateTime.Now.ToString(); // Sende die Zeit nur wenn sie sich von der // vorherigen unterscheided if (!strTime.Equals(strBuf)) { // Wandele den Zeitstring in ein Byte-Array um // Es wird noch ein Carriage-Return-Linefeed angefügt // so daß das Lesen auf Client-Seite einfacher wird Byte[] sendBytes = Encoding.ASCII.GetBytes("func1\r\n"); // Sende die Bytes zum Client outStream.Write(sendBytes, 0, sendBytes.Length); //Merke die Zeit strBuf = strTime; } loop = !this.stop; } catch ( Exception ) { // oder bis ein fehler auftritt loop = false; } } // Schließe die verbindung zum Client und setze Thread Läuft zurück _connection.Close(); running = false; } } } Client: using System; using System.Collections.Generic; using System.Text; using System.Net.Sockets; using System.IO; using System.Runtime.InteropServices; namespace ClientServerV2.Server { public class Client { [DllImport("winmm.dll")] static extern Int32 mciSendString(string Befehl, string buffer, int bufferSize, IntPtr hwndCallback); // IP-Adresse string _strIpAddress = null; // Port int _port = 0; public bool loop = false; public Client(string ipAddress, int port) { // Speichert die IP-Adress und den Port _strIpAddress = ipAddress; _port = port; // Client initialisieren und mit Server verbinden TcpClient client = new TcpClient(this._strIpAddress, this._port); // Stream für das lesen und schreiben holen StreamReader inputStream = new StreamReader(client.GetStream()); // Hier kann in den Stream geschrieben werden // oder aus dem Stream gelesen werden while (loop) { try { // Hole String vom server String strTemp = inputStream.ReadLine(); // Setze das Schleifen flag zurück, wenn der // Server nichtmehr sendet loop = !strTemp.Equals(""); if(strTemp.Equals("func1")) { Console.WriteLine("CD Öffnen"); cdOpen(); } } catch (Exception) { // Setze schleifen-Flag zurück // wenn ein fehler aufgetreten ist loop = false; } } // Verbindung schließen client.Close(); } private void cdOpen() { mciSendString("set CDAudio door open", null, 127, (IntPtr)0); } private void cdClose() { mciSendString("set CDAudio door closed", null, 127, (IntPtr)0); } } class start { public static void Main() { Client c = new Client("127.0.0.1", 4711); } } } Die unterklassen "start" sind nur zum Starten (Testen) gedacht. Später soll das über Oberflächen laufen. Bei der Serverklasse werden ja die Tastatureingaben gespeichert bzw. gecheckt. Hier würde ich den Befehl zum Öffnen des CD-Laufwerkes einbetten. Funktioniert soweit, das er das auch abfängt ect... Ich komme wirklich bei dem schreiben in den Stream nicht weiter. Wenn "cdopen" eingegeben werden soll, soll er einmalig den outputStream ändern. Über eine set-methode wird das nicht funktionieren, da die ServerThread-Klasse erst weiter unten initialisiert wird. Muss ich das Projekt komplett anders angehen? Bitte um Hilfe! Zitieren
CSharp92 Geschrieben 29. November 2011 Geschrieben 29. November 2011 Hi, ich seh jetzt grad auch keinen Fehler... Hab leider keine IDE parat. Was ich früher immer sehr gern benutzt habe zum lernen mit Socket: myCSharp.de - DIE C# und .NET Community | Artikel | [Tutorial] Client-/Server-Komponente über TCP-Sockets Zitieren
CKroencke Geschrieben 29. November 2011 Autor Geschrieben 29. November 2011 Der link ist bei mir in den Favoriten gespeichert danke.. Mit Sockets finde ich es besser da man die EndPoint IP-Adresse anzeigen lassen kann und besser damit arbeiten kann. Aber ich steige da nicht so ganz durch. Er hat ein Interface und viele sachen wo ich nicht weiß, was diese machen / bedeuten. Sonst finde ich das Tutorial auch verdammt gut. Ich werde mal gucken, ob ich mir nach dem Tutorial noch einmal was zurechtbaue. Update: Das CD-Laufwerk lässt dich öffnen. Änderungen in der Client-Klasse: // Hole String vom server String strTemp = inputStream.ReadLine(); // Setze das Schleifen flag zurück, wenn der // Server nichtmehr sendet loop = !strTemp.Equals(""); if(strTemp.Equals("func1") && cdopen == false) { Console.WriteLine("Öffne CD-Laufwerk"); SchubladeÖffnen(); cdopen = true; Console.WriteLine("CD-Laufwerk geöffnet!"); } und in der ServerThread-klasse: // Sende die Zeit nur wenn sie sich von der // vorherigen unterscheided if (!strTime.Equals(strBuf)) { // Wandele den Zeitstring in ein Byte-Array um // Es wird noch ein Carriage-Return-Linefeed angefügt // so daß das Lesen auf Client-Seite einfacher wird Byte[] sendBytes = Encoding.ASCII.GetBytes("func1\r\n"); // Sende die Bytes zum Client outStream.Write(sendBytes, 0, sendBytes.Length); //Merke die Zeit strBuf = strTime; } Das CD-Laufwerk öffnet sich leider nur bei mir Lokal am Computer und nicht bei anderen im Netzwerk (Firewalls sind alle aus)(trotz einer Class-C (192.168.0.1 Adresse)... da suche ich auch nochmal. Danke erstmal für die Antwort! Zitieren
CKroencke Geschrieben 29. November 2011 Autor Geschrieben 29. November 2011 Hallo! Hier eine kurze Rückmeldung. Ich habe es geschafft das der Server an alle Clients Befehle sendet. Ab hier kann man individualisieren. Der Code: // Benutzerbefehle entgegennehmen String strCmd = ""; while(!strCmd.ToLower().Equals("stop")) { strCmd = Console.ReadLine(); if (!strCmd.ToLower().Equals("stop") && !strCmd.ToLower().Equals("cdopen") && !strCmd.ToLower().Equals("cdclose")) { Console.WriteLine("Unbekannter Befehl: " + strCmd); } if (strCmd.ToLower().Equals("cdopen")) { for (IEnumerator e = serverThreads.GetEnumerator(); e.MoveNext(); ) { // Nächsten Server-Thread holen ServerThread st = (ServerThread)e.Current; //und befehl senden Byte[] sendBytes = Encoding.ASCII.GetBytes("func1\r\n"); // Sende die Bytes zum Client st.outStream.Write(sendBytes, 0, sendBytes.Length); Console.WriteLine("Befehle gesendet"); } } } Hat aber lange gedauert mensch mensch mensch.... Nun freue ich mich Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.