none
TCPClient senden/empfangen spacer RRS feed

  • Frage

  • Ich möchte einen TCPClient programmieren,
    ich bin momentan soweit, das ich Bytes zum server(ein Gerät) senden kann,
    jedoch muss ich noch die rückmeldung des servers angezeigt bekommen.

    Sprich: ich sende bytes, jenachdem welche Byteanordnung ich sende
    bekomme ich unterschiedliche meldungen zurück, jedoch weiß ich nicht
    recht mit der "recv Function" umzugehen um die ergebnisse in meinem
    Programm auszugeben.

    Was fehlt, damit ich auch empfangen kann?

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Net.Sockets;

    namespace TCPClient
    {
    class TCPClientClass
    {

    static void Main(string[] args)
    {

    TcpClient tcpClient = new TcpClient();
    tcpClient.Connect("Localhost", 1002);


    if (tcpClient.Connected)
    {
    NetworkStream NS = tcpClient.GetStream();

    Console.WriteLine("Bytemuster wird übertragen...");

    //ControlBytes als Hexdatei
    byte[] array = new byte[12];
    array[0] = 0x02; array[1] = 0x00; array[2] = 0x09;
    array[3] = 0x03; array[4] = 0x68; array[5] = 0x01;
    array[6] = 0x0E; array[7] = 0x57; array[8] = 0x00;
    array[9] = 0x01; array[10] = 0x03; array[11] = 0x03;

    //Hexdatein übertragen
    NS.Write(array, 0, 12);


    }
    }
    }
    }
    Montag, 12. September 2011 21:48

Antworten

  • Am 15.09.2011 14:34, schrieb Miele2008:
     
    > private  void  cmdSendenEmpfangen_Click_1(object  sender, EventArgs e)
    > {
    >    try
    >    {
    >       ns = client.GetStream();
    >       // hier schicke/schreibe ich 12 Byte in Networkstream
    >       ns.Write(request(), 0, 12);
    >
    >       // hier möchte ich die 12 Byte, die das Gerät schickt, aus dem Networkstream lesen
    >       //......
    >    }
     
    Dazu brauchst du keinen TcpListener oder sowas, auch nicht deine eigene
    IP Adresse, das geht ganz einfach mit Stream.Read(). Einen extra Start
    Button brauchst du auch nicht. Das ist sogenannte synchrone Übertragung,
    die funktioniert vielleicht erstmal, hat aber sonst nur Nachteile. Am
    besten du vergisst, dass es sowas überhaupt gibt. Die Nachteile sind so
    zahlreich, dass sie diesen Artikel sprengen würden.
     
    Besser ist asynchron, nicht mit Read(...), sondern mit BeginRead(...)
    und einer CallBack() Funktion, so wie in meinem ersten Beispiel. Der
    Callback wird automatisch aufgerufen wenn Daten ankommen, das wird durch
    BeginRead(...) initiiert. Dabei musst du nur aufpassen, dass dabei unter
    der Haube ein neuer Thread erzeugt wird, in welchem du keinen Zugriff
    auf das UI hast. Wenn du im UI vom Callback aus was manipulieren willst,
    musst du über Invoke(...) gehen.
     
    Wenn du aber trotz aller Empfehlungen unbedingt bei synchron bleiben
    willst, kannst du das so machen:
     
    private void cmdSendenEmpfangen_Click(object sender, EventArgs e)
    {
        Byte[] recvBuf = new Byte[123];
         try
        {
            Byte[] array = new Byte[]
            { 0x02,0x00,0x09,0x03,0x68,0x01,0x0E,0x57,0x00,0x01,0x03,0x03 };
            ns = Remote.GetStream();
            // hier schicke/schreibe ich 12 Byte in Networkstream
            ns.Write(array, 0, array.Length);
             // hier möchte ich die 12 Byte, die das Gerät schickt, aus dem
    Networkstream lesen
            //......
            int numRead = ns.Read(recvBuf, 0, recvBuf.Length);
        }
     
    Du kannst die Größe von Arrays überigens jederzeit zur Laufzeit
    bestimmen und auf deine magische '12' im Quelltext verzichten. Das
    bringt irgendwann nur Probleme, glaub es. Für wirklich robusten Code
    fehlt hier allerdings noch 'ne Menge Exception handling;
     
    Hajü
     
     
    • Als Antwort markiert Miele2008 Sonntag, 18. September 2011 15:37
    Donnerstag, 15. September 2011 15:03

Alle Antworten

  • Ich habe das wie folgt realisiert: Die Übertragung erfolgt asynchron,
    das ist auf jeden Fall vorzuziehen. Da brauchst du nicht explizit auf
    eine Antwort zu warten. Wann immer Daten ankommen wird der
    ReadCallback() automatisch aufgerufen. Ein paar aus dem Zusammenhang
    gerissene Fragmente (ich sende Text hin und her, der wird aber in Bytes
    konvertiert):
     
    Byte[] recvBuf = new Byte[1024];
    TcpClient Remote = new TcpClient(AddressFamily.InterNetwork);
     
    private void btnConnect_Click(object sender, EventArgs e)
    {
        try
        {
            Remote.Connect(tbHostname.Text, Convert.ToInt32(tbPort.Text));
            Remote.GetStream().BeginRead(recvBuf, 0, recvBuf.Length,
    ReadCallback, null);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
     
    private void btnSend_Click(object sender, EventArgs e)
    {
        Remote.GetStream().Write(Encoding.ASCII.GetBytes(strRequest), 0,
    strRequest.Length);
    } // End btnSend_Click
     protected void ReadCallback(IAsyncResult ar)
    {
        int numRead = 0;
        try
        {
            if (Remote.Connected == true)
                numRead = Remote.GetStream().EndRead(ar);
        }
        catch (IOException ex)
        {
            // Da bin ich mir nicht wirklich sicher, das passiert wenn der
    remote Host von sich aus die Verbindung unerwartet beendet.
            if (Marshal.GetHRForException(ex) == -2146232800)
                Invoke(new Action(DoDisconnect));
            else
                MessageBox.Show(ex.Message);
        }
         if (numRead > 0)
        {
            strResponse = Encoding.ASCII.GetString(recvBuf, 0, numRead);
            tbResponse.Invoke(new Action(UpdateResponse));
            // Start reading from the network again.
            Remote.GetStream().BeginRead(recvBuf, 0, recvBuf.Length,
    ReadCallback, recvBuf);
        }
    } // End ReadCallback
     
    Nebenbei bemerkt kannst du dein Datenarray besser so initialisieren
    byte[] array = new byte[] { 0x02, 0x00, 0x09, ... };
     
    Hajü
     
     
    Dienstag, 13. September 2011 10:01
  • Kleiner Zusatz, nicht
    NS.Write(array, 0, 12);
     
    sondern
    NS.Write(array, 0, array.Length);
     
    Wen sich die Arraygröße mal ändert, und das wird sie sicher, dann
    brauchst du nicht an mehreren Stellen was zu ändern.Eine potentielle
    Fehlerquelle weniger.
     
    Hajü
     
     
    Dienstag, 13. September 2011 10:21
  • Hallo Hajü,

     

    vielen Dank für deine Anwort und deine Bemerkung!

    Ich hab immer noch das Problem mit der Rückmeldung des Server(des Geräts).Also ich weiß es nicht wie ich die 12 byte, die ich an dem Gerät schicke, lesen kann. also ich schcike 12 byte und soll auch nur 12 byte zurückkommen.

    Hier habe ich das ganze Code was ich habe

    Ich hoffe du oder ihr könnt mir weiterhelfen

     

     

     

    private void cmdSendenEmpfangen_Click_1(object sender, EventArgs e)
    {

    try
    {
    ns = client.GetStream();
    // hier schicke/schreibe ich 12 Byte in Networkstream
    ns.Write(request(), 0, 12);

    // hier möchte ich die 12 Byte, die das Gerät schickt, aus dem Networkstream lesen
    //......

    }
    catch (Exception exp)
    {
    melde(exp.Message);
    return;
    }
    }



    public byte[] request()
    {
    byte[] array = new byte[12];
    array[0] = 0x02;
    array[1] = 0x00;
    array[2] = 0x09;
    array[3] = 0x03;
    array[4] = 0x68;
    array[5] = 0x01;
    array[6] = 0x0E;
    array[7] = 0x57;
    array[8] = 0x00;
    array[9] = 0x01;
    array[10] = 0x03;
    array[11] = 0x03;

    return array;
    }

    }
    }


     



    • Bearbeitet Miele2008 Sonntag, 18. September 2011 15:34
    Donnerstag, 15. September 2011 12:34
  • Am 15.09.2011 14:34, schrieb Miele2008:
     
    > private  void  cmdSendenEmpfangen_Click_1(object  sender, EventArgs e)
    > {
    >    try
    >    {
    >       ns = client.GetStream();
    >       // hier schicke/schreibe ich 12 Byte in Networkstream
    >       ns.Write(request(), 0, 12);
    >
    >       // hier möchte ich die 12 Byte, die das Gerät schickt, aus dem Networkstream lesen
    >       //......
    >    }
     
    Dazu brauchst du keinen TcpListener oder sowas, auch nicht deine eigene
    IP Adresse, das geht ganz einfach mit Stream.Read(). Einen extra Start
    Button brauchst du auch nicht. Das ist sogenannte synchrone Übertragung,
    die funktioniert vielleicht erstmal, hat aber sonst nur Nachteile. Am
    besten du vergisst, dass es sowas überhaupt gibt. Die Nachteile sind so
    zahlreich, dass sie diesen Artikel sprengen würden.
     
    Besser ist asynchron, nicht mit Read(...), sondern mit BeginRead(...)
    und einer CallBack() Funktion, so wie in meinem ersten Beispiel. Der
    Callback wird automatisch aufgerufen wenn Daten ankommen, das wird durch
    BeginRead(...) initiiert. Dabei musst du nur aufpassen, dass dabei unter
    der Haube ein neuer Thread erzeugt wird, in welchem du keinen Zugriff
    auf das UI hast. Wenn du im UI vom Callback aus was manipulieren willst,
    musst du über Invoke(...) gehen.
     
    Wenn du aber trotz aller Empfehlungen unbedingt bei synchron bleiben
    willst, kannst du das so machen:
     
    private void cmdSendenEmpfangen_Click(object sender, EventArgs e)
    {
        Byte[] recvBuf = new Byte[123];
         try
        {
            Byte[] array = new Byte[]
            { 0x02,0x00,0x09,0x03,0x68,0x01,0x0E,0x57,0x00,0x01,0x03,0x03 };
            ns = Remote.GetStream();
            // hier schicke/schreibe ich 12 Byte in Networkstream
            ns.Write(array, 0, array.Length);
             // hier möchte ich die 12 Byte, die das Gerät schickt, aus dem
    Networkstream lesen
            //......
            int numRead = ns.Read(recvBuf, 0, recvBuf.Length);
        }
     
    Du kannst die Größe von Arrays überigens jederzeit zur Laufzeit
    bestimmen und auf deine magische '12' im Quelltext verzichten. Das
    bringt irgendwann nur Probleme, glaub es. Für wirklich robusten Code
    fehlt hier allerdings noch 'ne Menge Exception handling;
     
    Hajü
     
     
    • Als Antwort markiert Miele2008 Sonntag, 18. September 2011 15:37
    Donnerstag, 15. September 2011 15:03
  • vielen Dank für deine Antwort..es hat geklappt!

    MfG

    Sonntag, 18. September 2011 15:37