C# Ausgabe von Serverdaten auf Client via Stream und Bluetooth

palaber

Captain
Registriert
Juni 2006
Beiträge
3.856
Servus,
ich schon wieder. Aktuell verbinde ich 2 Rechner via BT. Der eine als Server, den andere als Client.
Die Verbinung aufbauen geht. Momentan begnüge ich mich damit aus einer Textbox einen Text am
anderen Rechner auszugeben.

Ich kann z.B. vom Client zum Server einen Text schicken, der dann in einer Textbox ausgegeben wird.
Möchte ich nun Text vom Server zum Client schicken funktioniert das nicht.
Hier mal der betreffende Clientcode:
Code:
       private void ClientConnectThread() 
        { 
            BluetoothClient client = new BluetoothClient(); 
            updateUI("Verbindungsaufbau...");

            client.BeginConnect(deviceInfo.DeviceAddress, mUUID, this.BluetoothClientConnectCallback, client); 
        }

       
        
        void BluetoothClientConnectCallback(IAsyncResult result)        
        {

            //TRY CATCH REIN für Timeout!            
            BluetoothClient client = (BluetoothClient)result.AsyncState;            
            client.EndConnect(result);            
            Stream stream = client.GetStream();
            updateUI("ClientConnectCallback: Client - Server Verbindung steht");

            stream.ReadTimeout = 1000;

            while (true)            
            {
                while (ready)
                {
                    stream.Write(message, 0, message.Length);
                    ready = false;
                }      
            }        
        }

ich habe probiert in "BluetoothClientConnectCallback" Code zu implementieren, der mir dann entsprechend die GUI TB updatet. Allerdings hab ich das Problem, dass es dann im Server ne Loop fährt mit nem String + meinem Byte[]. Außerdem ist das senden von Daten an den Client dann auch nicht mehr möglich.
Hier mal der erweiterte Code:
Code:
void BluetoothClientConnectCallback(IAsyncResult result)        
        {
            //TRY CATCH REIN für Timeout!            
            BluetoothClient client = (BluetoothClient)result.AsyncState;            
            client.EndConnect(result);            
            Stream stream = client.GetStream();
            updateUI("ClientConnectCallback: Client - Server Verbindung steht");

            stream.ReadTimeout = 1000;
            try
            {
                byte[] empfangen = new byte[1024];
                stream.Read(empfangen, 0, empfangen.Length);
                this.updateUI("Schleife im Client Code!: " + Encoding.ASCII.GetString(empfangen));
            }
            catch (Exception e) { string sFehlercode = e.ToString(); }

            while (true)            
            {
                while (ready)
                {
                    stream.Write(message, 0, message.Length);
                    ready = false;
                }      
            }        
        }

Hab schon einiges rum probiert, aber nie das gewünschte Ergebniss gefunden. Und solangsam seh ich den Wald vor lauter Bäumen nich mehr.
 
Hallo,

Ohne gerade zu wissen, wie das in C# genau funktioniert, gehe ich von aus, dass die Callbacks Benachrichtigungen/Events über eingehende Nachrichten sind.

Korrektur: Nah dran, es ist nur die (einmalige) Benachrichtigung über das Ergebnis des Connects. Dort kann man anschließend fortfahren und auf ähnliche Weise auf Nachrichten lauschen (vgl. MSDN Beispiel).

In jedem Fall blockieren die while-Schleifen in Zeile 18 und 20 ein erfolgreiches Beenden der Verarbeitung einer Nachricht.
Die innere while(ready) terminiert nach dem ersten Durchlauf, die äußere jedeoch NIE.

Vermutlich legt das dann alles lahm.
 
Zuletzt bearbeitet: (Inhaltliche Korrektur)
Also in meiner ClientConnectCallback Methode wird durch die Endlosschleife das senden ermöglicht. Immer wenn ich auf senden drücke wird etwas in den Stream geschrieben.
Dann müsste ich doch auch in jedem durchlauf testen können, ob was im stream liegt und wenn ja soll mir das ausgegeben werden, oder?

Ich hab mir mal das Bsp. angeschaut. Das kann ich aber nicht so umsetzten, da ich mit der InTheHand Bib arbeite und diese mir z.B. "Socket" gar nicht anbietet. Außerdem ruf ich aus dem Connect Thread keine weitere Method aus. Sieht dann so aus:
Code:
 private void ClientConnectThread() 
        { 
            BluetoothClient client = new BluetoothClient(); 
            updateUI("Verbindungsaufbau...");

            client.BeginConnect(deviceInfo.DeviceAddress, mUUID, this.BluetoothClientConnectCallback, client);
        }

und dann geh ich in die Callback Funktion:
Code:
void BluetoothClientConnectCallback(IAsyncResult result)        
        {
            //TRY CATCH REIN für Timeout!            
            BluetoothClient client = (BluetoothClient)result.AsyncState;            
            client.EndConnect(result);            
            Stream stream = client.GetStream();
            updateUI("Verbunden mit: " + client.RemoteEndPoint.ToString());

            stream.ReadTimeout = 1000;
            
            while (true)
            {
                stream.ReadTimeout = 1000;

                try
                {
                    stream.Read(empfangen, 0, empfangen.Length);
                    updateUI("\r\nEmpfangen: " + Encoding.ASCII.GetString(empfangen));
                }

                catch (Exception e) {};


                while (ready)
                {
                    updateUI("Daten gesendet: " + Encoding.ASCII.GetString(message));
                    stream.Write(message, 0, message.Length);
                    ready = false;
                }
            }  
        }
Ich mein hier testet er ja auch ständig ob es was zum schreiben gibt. Und immer wenn es etwas gibt (durch klick auf Button wird read auf true gesetzt) sendet mir der Client etwas auf den Server. Warum kann ich denn dann an dieser stelle nicht auch auf dem Stream lauschen und dann etwas ausgeben?!

Edit: in try/catch wirft er mir bei der Ausgabe folgendes: System.NullReferenceException: Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt!

Im Server sieht das dann so aus:
Code:
public void ServerConnectThread()        
        {

            serverStarted = true;       //Bool zum verhindern des mehrfachstarts dieses Threads
            BluetoothListener btListener = new BluetoothListener(mUUID);

            btListener.Start();
            updateUI("Warte auf Verbindung...");

            BluetoothClient connect = new BluetoothClient();
            connect = btListener.AcceptBluetoothClient();
            updateUI("Client connected");
              
            Stream mStream = connect.GetStream();

            while (true)            
            {     
                //Hier wird der Stream ausgelesen und falls etwas übertragen wurde ausgegeben              
                byte[] received = new byte[1024];
                Array.Clear(received, 0, received.Length);

                try                
                {
                    mStream.Read(received, 0, received.Length);                    
                    updateUI("Empfangen: " + Encoding.ASCII.GetString(received));                    
                }                
                catch (IOException e) { } 

                //Hier soll in den Stream geschrieben werden, wenn auf button senden gecklickt wurde
                if (ready==true)                    
                {                        
                    mStream.Write(message, 0, message.Length); 
                    updateUI(Encoding.ASCII.GetString(message));   
                    ready = false;                     
                }  
            }        
        }
 
Zuletzt bearbeitet:
palaber schrieb:
in try/catch wirft er mir bei der Ausgabe folgendes: System.NullReferenceException
Die Variable empfangen ist NULL.
 
Schau doch mal hier in der Dokumentation von deiner 32feet-DLL rein, da gibts eine Beispielapplikation BluetoothChat2:
http://32feet.codeplex.com/wikipage?title=Sample%20programs&referringTitle=Documentation

Im Quellcode gibt es da den Ordner "InTheHand.NET.Personal >> Samples >> BluetoothChat2".

Ich denk, wenn du dir das mal anschaust, dann findest du den Dreh raus ;-)

Anmerkung zu deinem Code: Entweder ich überseh dich Variablen-Deklarationen irgendwo oder die sind alle in der ganzen Klasse bekannt. Kann insofern hinderlich sein, alls dass es dann bei parallelen Zugriffen Probleme gibt.
Benutz wo es nur geht lokale Variablen, die nur für einen Block / Funktion gelten, damit die nicht mehrfach benutzt werden und zufällig weil alte Werte halten.

Generell denke ich, du musst das Senden und Empfangen von Nachrichten trennen.

Halte dir ein Klassenweites Objekt der Verbindung und lausche auf Events wenn die Verbindung abbricht + wenn eine Nachricht rein kommt.
Mach dir einen Button-Click-Handler oder ähnliches, mit dem du vom Nutzer geschriebenen Text erst beim Button-Click über das Verbindungs-Objekt an die Gegenstelle schickst.

Generell sollte der gleiche Code beim Server, wie beim Client stehen. Ob dann serverseitig direkt und automatisch geantwortet wird ist ja nachgelagert.

Zum Senden:
Wenn du eine Nachricht auf den Stream geschrieben hast solltest du eine Antwort implementieren, dass die Nachricht erfolgreich angekommen ist und beim Sender darauf warten, oder es nochmal probieren. Im Empfänger musst du natürlich nach Empfang und Prüfung der Nachricht die Antwort auch noch schicken.
 
Zurück
Oben