Zum Inhalt springen

TcpListener & Client, Bytes senden und Empfangen(wie?), Mutli-Client Server


CKroencke

Empfohlene Beiträge

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!

Link zu diesem Kommentar
Auf anderen Seiten teilen

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!

Link zu diesem Kommentar
Auf anderen Seiten teilen

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 :D

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...