none
Socket Senden&Empfangen RRS feed

  • Frage

  • Hallo!

    Wie sicher ist so eine Verbindung?

    Ich sende einen String, serialiere den, bis dato keine Fehler festgestellt.
    Dennoch, müsste ich evtl. vorab die Länge prüfen?

    Es gibt ja Protokolle, die die Länge voranstellen, um das Ende mitzubekommen.
    Wer stellt sicher, dass alles empfangen wird?
    Macht das Microsoft intern?

    DataAvailable
            private System.Net.Sockets.TcpClient MyTcpClient;
            private System.Net.Sockets.NetworkStream MyNetworkStream;

    Wenn ja, wie würde man das am Sinnvollsten realisieren?

                    UTF8Encoding encoding = new UTF8Encoding();
                    byte[] ba = encoding.GetBytes(data);
                    System.Diagnostics.Trace.WriteLine("\r\nÜbertrage zum Server : \"" + data + "\"");
                    MyTcpStream.Write(ba, 0, ba.Length);

                    byte[] buffer = new byte[MyMaxBuffer];
                    int gelesen = MyTcpStream.Read(buffer, 0, MyMaxBuffer);

                    string empfangen = encoding.GetString(buffer, 0, gelesen);

    Für Tipps sage ich vorab Danke.

    Viele Grüße Andreas

    Dienstag, 3. Mai 2011 13:27

Antworten

  • Machs do mit einer do .. while Schleife

     

     

    string empfangen = String.Empty;
    if(MyTcpStraem.DataAvailable){
     do
     {
      int gelesen = MyTcpStream.Read(buffer, 0, MyMaxBuffer);
      empfangen += encoding.GetString(buffer, 0, gelesen);
    
     }while (MyTcpStraem.DataAvailable)
    }

     


    Florian Kowalsky -> If it was helpful please mark ist as helpful!!
    Dienstag, 3. Mai 2011 15:24

Alle Antworten

  • Hallo Andreas,

    anders gefragt: Warum verwendest Du überhaupt Sockets? Je nach Anforderung gibt es u.U. schon fertige Lösungen, die für dich erheblich weniger Arbeit bedeuten, eben weil dort schon sämtliche Prüfungen, ... im Vorfeld stattfinden und Du dann "nur noch" mit den Daten arbeiten musst.

     


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
    Dienstag, 3. Mai 2011 15:21
    Moderator
  • Machs do mit einer do .. while Schleife

     

     

    string empfangen = String.Empty;
    if(MyTcpStraem.DataAvailable){
     do
     {
      int gelesen = MyTcpStream.Read(buffer, 0, MyMaxBuffer);
      empfangen += encoding.GetString(buffer, 0, gelesen);
    
     }while (MyTcpStraem.DataAvailable)
    }

     


    Florian Kowalsky -> If it was helpful please mark ist as helpful!!
    Dienstag, 3. Mai 2011 15:24
  • anders gefragt: Warum verwendest Du überhaupt Sockets? Je nach Anforderung gibt es u.U. schon fertige Lösungen, die für dich erheblich weniger Arbeit bedeuten, eben weil dort schon sämtliche Prüfungen, ... im Vorfeld stattfinden und Du dann "nur noch" mit den Daten arbeiten musst.

     


    Hallo,

    wie meinst Du das? Ironisch?

    Wa soll ich verwenden?

    Andreas

    Dienstag, 3. Mai 2011 15:25
  •  

    string empfangen = String.Empty;
    
    if(MyTcpStraem.DataAvailable){
    
     do
    
     {
    
     int gelesen = MyTcpStream.Read(buffer, 0, MyMaxBuffer);
    
     empfangen += encoding.GetString(buffer, 0, gelesen);
    
    
    
     }while (MyTcpStraem.DataAvailable)
    
    }

     

    Hallo Florian,

    ok, das heißt ein vorheriges Senden der Anzahl ist nicht notwendig.

    Also in etwas so

        4 Byte die Länge + Telegramm ?

    So wäre es ja einfacher.

    Andreas

     

    Dienstag, 3. Mai 2011 15:27
  • Hallo Andreas,

    wie meinst Du das? Ironisch?

    Nö.

    Wa soll ich verwenden?

    Das kommt auf deine Anforderungen an. Evtl. hast Du die schon mal in einem anderen Thread beschrieben. Falls ja, poste doch bitte mal einen Link.

    Einfaches Beispiel: Um Daten an einen Webservice zu übertragen, schreibt man auch nicht alles von Hand, sondern nutzt bspw. ASP.NET Webservices, WCF, .... Für die Übertragung selbst dann bspw. Json, Xml, ...

    Dass das evtl. nicht genau bei dir passt, ist klar. Daher ja auch die Frage: Was machst Du da eigentlich genau? Evtl. gibt es ja dann erheblich einfachere Lösungen.

     


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
    Dienstag, 3. Mai 2011 16:01
    Moderator
  • Das kommt auf deine Anforderungen an. Evtl. hast Du die schon mal in einem anderen Thread beschrieben. Falls ja, poste doch bitte mal einen Link.

    Einfaches Beispiel: Um Daten an einen Webservice zu übertragen, schreibt man auch nicht alles von Hand, sondern nutzt bspw. ASP.NET Webservices, WCF, .... Für die Übertragung selbst dann bspw. Json, Xml, ...

    Dass das evtl. nicht genau bei dir passt, ist klar. Daher ja auch die Frage: Was machst Du da eigentlich genau? Evtl. gibt es ja dann erheblich einfachere Lösungen.

    Hallo Stefan,

    ok. Ich dachte halt weil ich so oft frage.

    http://social.msdn.microsoft.com/Forums/de-DE/visualcsharpde/thread/f2b53154-fb7a-4352-9758-4152014ae679
    http://social.msdn.microsoft.com/Forums/de-DE/visualcsharpde/thread/d5a8ce50-446c-4cb8-9132-87c224ec9427

    Ja ich hatte große Probleme mit dieser Herausforderung und war froh es einigermaßen zum Laufen gebracht haben.
    Tut auch.
    Es kam die Frage auf, wie stelle ich sicher, dass alles empfangen wurde.

    http://de.wikipedia.org/wiki/Byte_Order_Mark
    http://de.wikipedia.org/wiki/Big_endian
    Muss man das so kompliziert machen? Bietet Windows was?
    Braucht man das?

    Fragen über Fragen.

    Die Idee von Florian ist gut und verständlich.

    OK vielleicht über SOAP irgendwas noch...?

     

    Andreas

    Dienstag, 3. Mai 2011 17:49
  • Hallo Andreas,

    zu Deiner Frage habe ein paar Anmerkungen.

    Zum ersten ist es wichtig zu wissen, dass Verfahren die intern ein Msg-Peek (Abfrage) auf dem Socket umsetzen (auch das DataAvailabe), normal nicht zu empfehlen sind.

    [INFO: Avoid Data Peeking in Winsock]
    http://support.microsoft.com/kb/192599/en-us

    Aus: http://www.cetix.de/DotNetNews/Thread94063-prfen_ob_TCClient_noch_da_ist.aspx:

    • ... solche Schleifen mit 'DataAvailable' und Sleep sind höchst unüblich/unsauber... (und beendete Verbindungen bemerkt man so nicht). Vergiss 'DataAvailable', mache eine ordentliche Lese-Schleife mit synchron Socket.Receive / NetworkStream.Read
      oder asynchron (Vorsicht, Callback erfolgt mit Pool-Threads) Socket.BeginReceive / NetworkStream.BeginRead
      oder eben u.U. halt Socket.Select/Socket.Poll.

    Aus: http://www.eggheadcafe.com/software/aspnet/36133229/prob-mit-image-via-tcp-senden-und-empfangen.aspx:

    Microsoft hat hier kein Standard-Verfahren wie es das standardmäßig macht, sondern Szenarien-abhängig. 
    Allerdings "wenn" eine Länge mit gesendet werden soll, dann wird normal 4 Byte am Anfang benutzt und dann der Daten tragende serialisierte Stream.

    [Data Driven Silverlight Applications for the Enterprise]
    http://msdn.microsoft.com/en-us/magazine/dd315415.aspx

    siehe dort: "Figure 6 Layout of the Serialized NetworkMessage Types"

    Eine solche Vorschaltung eines int's in den NetworkStream ist möglich, aber nicht notwendig.
    Bei kleiner ReceiveBufferSize, SendBufferSize kann hier ggf. durchaus ohne solche Längen gearbeitet werden.
    Es gibt verschiedene Ansätze und Verfahren.

    Hier ein auch Beispiel:

    [Client-Server Kommunikation mit dem TcpClient und TcpListener]
    http://dzaebel.net/TcpClientServer.htm

    es geht natürlich auch asynchron:

    [Asynchronous Server Socket using C# | C# Help]
    http://www.csharphelp.com/2007/02/asynchronous-server-socket-using-c/


    ciao Frank
    Dienstag, 3. Mai 2011 19:01
  • [Client-Server Kommunikation mit dem TcpClient und TcpListener]
    http://dzaebel.net/TcpClientServer.htm

     private void btnOK_Click(object sender, EventArgs e)
      {
       try
       {
        tcpStream = tcpClient.GetStream();
        UTF8Encoding encoding = new UTF8Encoding();     //Arbeiten Sie hier später über Decoder! Thema Fragmentierung von Doppelbytes.
        byte[] ba = encoding.GetBytes(txtÜbertragungstext.Text);
        Melde("\r\nÜbertrage zum Server : \"" + txtÜbertragungstext.Text + "\"");
        tcpStream.Write(ba, 0, ba.Length);
        byte[] buffer = new byte[maxBuffer];
        int gelesen = tcpStream.Read(buffer, 0, maxBuffer);
        string empfangen = encoding.GetString(buffer,0,gelesen);
        Melde("Empfangen: \"" + empfangen + "\"");
       }
       catch (Exception exp) { Melde(exp.Message); return; }
      }
    
    
    

    Hallo Frank , so habe ich es ja übernommen und festgestellt, dass Read halt liest.

    Grüße Andreas

    Dienstag, 3. Mai 2011 19:42

  • Florian Kowalsky -> If it was helpful please mark ist as helpful!!


    Hallo Florian,

    ich habe es erst so

        TcpClient MyTcpClient;
        //Stream MyTcpStream;
        NetworkStream MyTcpStream;
    

    Deshalb kannte ich DataAvailable nicht.

    Trotzdem es sind Daten da, es wird nicht gesetzt. Und nun?

    Es wäre zumindest eine einfache verständliche Lösung.

    http://www1.minpic.de/bild_anzeigen.php?id=145091&key=34843918&ende

     Ist ja auch so gemacht.

    http://msdn.microsoft.com/de-de/library/system.net.sockets.networkstream.dataavailable.aspx

     string empfangen = String.Empty;
            int gelesen = 0;
    
            if (MyTcpStream.CanRead)
            {
              byte[] buffer = new byte[MyMaxBuffer];
    
              //if (MyTcpStream.DataAvailable)
              //{
                do
                {
                  gelesen = MyTcpStream.Read(buffer, 0, MyMaxBuffer);
                  //empfangen = encoding.GetString(buffer, 0, gelesen);
                  empfangen += encoding.GetString(buffer, 0, gelesen);
                } while (MyTcpStream.DataAvailable);
              //}
            }
    
    Andreas
    Mittwoch, 4. Mai 2011 16:20