Laden...

UDP Mehrere Daten gleichzeitig senden und empfangen

Erstellt von dev.pr vor 6 Jahren Letzter Beitrag vor 6 Jahren 3.155 Views
D
dev.pr Themenstarter:in
22 Beiträge seit 2017
vor 6 Jahren
UDP Mehrere Daten gleichzeitig senden und empfangen

Hallo liebe Community,
ich habe ein kleines Problem, ich bin gerade dabei ein kleines Spiel zu schreiben was man zu 2 über UDP spielen kann. Ja ich weiß auch das UDP nicht die beste Lösung ist aber meine Schule möchte es so.
Ich habe eine Verbindung erfolgreich aufgebaut und bekomme auch erfolgreich daten gesendet und empfangen, jedoch sind diese dann verwurschtelt (nehme ich an). Mein Ziel ist es das wenn ich meine PictureBox bewege, sie sich auf dem anderen Bildschirm auch bewegt, also quasi die Daten von Spieler1 an Spieler2 senden und von Spieler2 an Spieler1. Wenn ich nur die Y-Koordinate sende klappt alles, aber sobald ich die x-koordinate mit sende klappt es nicht mehr. Hier mal mein Code:


private void UDPSENDER_Tick(object sender, EventArgs e)
        {

            //ALG 
            // 0 = X-Wert des Spieler1
            // 1 = Y-Wert des Spieler1
            // 2 = Coin-Koordinate X
            // 3 = Coin-Koordinate Y
            System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
            byte[] msg = new byte[1500];
            if(udpalg == 0)
            {
                msg = enc.GetBytes(x.ToString());
                sck.Send(msg);
                udpalg++;
            }
            else if (udpalg == 1)
            {
                msg = enc.GetBytes(y.ToString());
                sck.Send(msg);
                udpalg++;
            }
            else if (udpalg == 2)
            {
                msg = enc.GetBytes(pictureBox1.Location.X.ToString());
                sck.Send(msg);
                udpalg++;
            }
            else if (udpalg == 3)
            {
                msg = enc.GetBytes(pictureBox1.Location.Y.ToString());
                sck.Send(msg);
                udpalg = 0;
            }
        }

Da werden die Daten gesendet,
hier werden sie empfangen:


private void MessageCallBack(IAsyncResult aResult)
        {
            try
            {
                int size = sck.EndReceiveFrom(aResult, ref epRemote);
                if (size > 0)
                {
                    byte[] receivedData = new byte[1464];
                    receivedData = (byte[])aResult.AsyncState;
                    ASCIIEncoding eEncoding = new ASCIIEncoding();
                    string receivedMessage = eEncoding.GetString(receivedData);
                    //ALG 
                    // 0 = X-Wert des Spieler1
                    // 1 = Y-Wert des Spieler1
                    // 2 = Coin-Koordinate X
                    // 3 = Coin-Koordinate Y
                    if (udpalg == 0)
                    {
                        S2X = Convert.ToInt32(receivedMessage);
                    }
                    else if (udpalg == 1)
                    {
                        S2Y = Convert.ToInt32(receivedMessage);
                    }
                    else if (udpalg == 2)
                    {
                        Coinx = Convert.ToInt32(receivedMessage);
                    }
                    else if (udpalg == 3)
                    {
                        Coiny = Convert.ToInt32(receivedMessage);
                    }
                    S2.Location = new Point(S2X, S2Y);
                    pictureBox1.Location = new Point(Coinx, Coiny);


                }

                byte[] buffer = new byte[1500];
                sck.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref epRemote, new AsyncCallback(MessageCallBack), buffer);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
            }
        }

was mache ich falsch?

LG

Never trust a running system.

Youtube

16.806 Beiträge seit 2008
vor 6 Jahren

UDP ist für Spiele und Video-Übertragung i.d.R. besser als TCP.
Bei solchen Anwendungen stört es nicht, wenn ein Datenpaket fehlt und ein Nachsenden eines Datenpakets bringt ja in den meisten Szenarien solcher Anwendungen dann auch nichts mehr.

"Klappt nicht" ist keine akzeptable Fehlermeldung in einem Forum. Keiner hat hier lust zu raten.
Bitte beachte [Hinweis] Wie poste ich richtig? insbesondere Punkt 5.

D
dev.pr Themenstarter:in
22 Beiträge seit 2017
vor 6 Jahren

Hallo, danke erst einmal für die schnelle Antwort.

Also so wie das Programm da steht passiert folgendes:

Die X Position von S2 bewegt sich, jedoch nicht die Y Position und der Coin bewegt sich komplett garnicht.

Ich habe mal geschaut, die Picturebox S2 nimmt alle Werte an, dass heißt ich sende von S1 die X und Y werte und von dem Coin(ist auch eine Picturebox) auch die X und Y Werte und beim empfangen greift sich S2 alle Werte und springt dann immer zwischen 4 Werten rum, ich hoffe ich konnte mich gut ausdrücken.

nochmal zusammengefasst S2 denkt das S1 XundY Werte und Coin XundY Werte für S2 als X-Wert gedacht ist

Never trust a running system.

Youtube

849 Beiträge seit 2006
vor 6 Jahren

Hallo,

ich denke du vergisst in deiner MessageCallback Methode udpalg zu inkrementieren.
Ist aber auch gefährlich, denn wenn ein Udp Packet nicht ankommt oder der sender neu gestartet wird, kommt deine Logik vollkommen durcheinander.

D
dev.pr Themenstarter:in
22 Beiträge seit 2017
vor 6 Jahren

Hallo, habe es inkrementiert, und ja es kommt sehr schnell durcheinander.

Kennt jemand noch eine andere möglichkeit so etwas zu regeln?

danke erstmal trotzdem für die Hilfe.

LG

Never trust a running system.

Youtube

4.930 Beiträge seit 2008
vor 6 Jahren

Warum sendest du denn nicht alle 4 Werte in einer Nachricht?
Und besser wäre es auch, die Werte direkt binär zu verschicken anstatt als Strings. Schau dir dazu mal die Klassen BinaryWriter und BinaryReader an.

D
dev.pr Themenstarter:in
22 Beiträge seit 2017
vor 6 Jahren

Hallo, weil ich nicht weiß wie ich diese 4 Werte dann wieder trennen soll wenn ich sie erhalt, kannst du mir sagen wie man sowas trennt?

ja werde ich mir mal anschauen danke

Never trust a running system.

Youtube

4.930 Beiträge seit 2008
vor 6 Jahren

Du brauchst diese nicht trennen, da du diese einfach der Reihe nach mit dem BinaryReader aus dem Stream liest (die Grunddatentypen wie int sind binär immer gleich groß):


var binaryReader = new BinaryReader(message);
int x = binaryReader.ReadInt32();
int y = binaryReader.ReadInt32();
// ...

D
dev.pr Themenstarter:in
22 Beiträge seit 2017
vor 6 Jahren

Hallo,

Werde es gleich mal ausprobieren und mal schauen ob es klappt, vielen dank!

Never trust a running system.

Youtube

D
dev.pr Themenstarter:in
22 Beiträge seit 2017
vor 6 Jahren

Hallo, habe es nicht ganz hinbekommen, deine Variable (Message) habe ich durch receivedMessage ersetzt, hat als string nicht funktioniert und als integer auch nicht. Und beim senden klappt es auch noch nicht so ganz, wenn ich die daten empfange mache ich glaube ich noch einen fehler.


                    byte[] receivedData = new byte[1464];
                    receivedData = (byte[])aResult.AsyncState;
                    ASCIIEncoding eEncoding = new ASCIIEncoding();
                    string receivedMessage = eEncoding.GetString(receivedData);
                    int message = Convert.ToInt32(receivedMessage, 2);
                    var binaryReader = new BinaryReader(message);
                    int x = binaryReader.ReadInt32();
                    int y = binaryReader.ReadInt32();

Never trust a running system.

Youtube

16.806 Beiträge seit 2008
vor 6 Jahren

Willst Du den Helfern nicht ein paar mehr Informationen zukommen lassen als "klappt nicht" und "funktioniert nicht"?
[Hinweis] Wie poste ich richtig? Punkt 5

4.930 Beiträge seit 2008
vor 6 Jahren

Hallo dev.pr,

du solltest dich mal intensiver mit den (Standard-)Datentypen auseinandersetzen.
Der BinaryReader erwartet ein Byte-Array, und das hast du doch schon als receivedData vorliegen, also kannst du dieses direkt übergeben (das ganze Konvertieren ist also überflüssig).

PS: Außerdem ist das Initialisieren des Byte-Arrays sinnfrei, da du es ja in der nächsten Zeile wieder neu zuweist. Es reicht also


byte[] receivedData = (byte[])aResult.AsyncState;

Und da BinaryReader die IDisposable-Schnittstelle implementiert, müßte man dann korrekterweise noch Dispose() aufrufen, bzw. eleganter mittels


using (var binaryReader = new BinaryReader(receivedData))
{
    int x = binaryReader.ReadInt32();
    int y = binaryReader.ReadInt32();
}

Und das selbe mußt du dann natürlich auch beim Senden umsetzen.