Entwickler-Ecke

Netzwerk - TCP Client in Byte senden...


tomycat - Fr 08.03.19 08:53
Titel: TCP Client in Byte senden...
hallo,


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
static void Connect(String server, String message) 
{
  try 
  {
    // Create a TcpClient.
    // Note, for this client to work you need to have a TcpServer 
    // connected to the same address as specified by the server, port
    // combination.
    Int32 port = 13000;
    TcpClient client = new TcpClient(server, port);
    
    // Translate the passed message into ASCII and store it as a Byte array.
    Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);         

    // Get a client stream for reading and writing.
   //  Stream stream = client.GetStream();
    
    NetworkStream stream = client.GetStream();

    // Send the message to the connected TcpServer. 
    stream.Write(data, 0, data.Length);

    Console.WriteLine("Sent: {0}", message);         

    // Receive the TcpServer.response.
    
    // Buffer to store the response bytes.
    data = new Byte[256];

    // String to store the response ASCII representation.
    String responseData = String.Empty;

    // Read the first batch of the TcpServer response bytes.
    Int32 bytes = stream.Read(data, 0, data.Length);
    responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
    Console.WriteLine("Received: {0}", responseData);         

    // Close everything.
    stream.Close();         
    client.Close();         
  } 
  catch (ArgumentNullException e) 
  {
    Console.WriteLine("ArgumentNullException: {0}", e);
  } 
  catch (SocketException e) 
  {
    Console.WriteLine("SocketException: {0}", e);
  }
    
  Console.WriteLine("\n Press Enter to continue...");
  Console.Read();

1.Frage
So funkt es 1a...

C#-Quelltext
1:
2:
  message = "BINX";
  Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
Jetzt will ich es aber als Byte senden...

C#-Quelltext
1:
2:
// Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
  Byte[] data = {42,49,4e,58}; // 4e ist rot

Idee 2:

C#-Quelltext
1:
2:
// Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
  Byte[] data = {42,49,44,58}; // so ist alles im grünen Bereich

Mit Wireshark sehe ich dass *1,: übertragen wird. Wieso?

2.Frage.
Egal wie ich die Funktion sende aufrufe, es blockiert das ganze Programm. Naja, die Funktion erwartet eine Antwort. Aber wie könnte die Lösung aussehen? 2 Sekunden warten? Thread verwenden? oder als try read?

Moderiert von user profile iconTh69: C#-Tags hinzugefügt


Th69 - Fr 08.03.19 09:47

Du hast dich zwischen dezimal und hexadezimal vertan, s.a. ASCII-Tabelle [https://de.wikipedia.org/wiki/American_Standard_Code_for_Information_Interchange#ASCII-Tabelle].
Für hexadezimal mußt du 0x als Prefix benutzen.

Und ja, NetworkStream.Read blockiert, solange nicht genügend Daten vorliegen. Für die Umsetzung gibt es verschiedene Möglichkeiten (Thread, Task bzw. async).
Suche am besten mal nach einem Tutorial dazu, z.B. Async Programming : Asynchronous TCP Sockets as an Alternative to WCF [https://msdn.microsoft.com/en-us/magazine/dn605876.aspx] oder Async TCP Client [https://riptutorial.com/csharp/example/28048/async-tcp-client].

PS: Bitte verwende die richtigen C#-Tags (nicht {{{ ... }}}, sondern [cs]...[/cs]).


tomycat - Fr 08.03.19 13:23


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
  private void button1_Click(object sender, EventArgs e)
        {

            Console.WriteLine("Button1 wurde gedrückt");
            Thread t = new Thread(new ThreadStart(ThreadProc));
            t.Start();
            Console.WriteLine("Los gehts");

        }

        public static void ThreadProc()
        {
            string server = "mein_ftp_server";
            string message = "hello_Server";
            try
            {
              
                Int32 port = 21;
                TcpClient client = new TcpClient(server, port);

                // Translate the passed message into ASCII and store it as a Byte array.
                Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

                // Get a client stream for reading and writing.
                //  Stream stream = client.GetStream();

                NetworkStream stream = client.GetStream();

                // Send the message to the connected TcpServer. 
                stream.Write(data, 0, data.Length);

                Console.WriteLine("Sent: {0}", message);

                // Receive the TcpServer.response.

                // Buffer to store the response bytes.
                data = new Byte[256];

                // String to store the response ASCII representation.
                String responseData = String.Empty;

                // Read the first batch of the TcpServer response bytes.
                Int32 bytes = stream.Read(data, 0, data.Length);
                responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
                Console.WriteLine("Received: {0}", responseData);

                // Close everything.
                stream.Close();
                client.Close();
            }
            catch (ArgumentNullException e)
            {
                Console.WriteLine("ArgumentNullException: {0}", e);
            }
            catch (SocketException e)
            {
                Console.WriteLine("SocketException: {0}", e);
            }

            Console.WriteLine("\n Press Enter to continue...");
            Console.Read();
        }


so würde es gehen, aber wie könnte der Button1 den Text hello_server dem Thread übergeben? Ich dachte wie eine Funktion, geht aber leider nicht.


Ralf Jansen - Fr 08.03.19 13:48

Für die einmalige Kommunikation (Thread nach der Kommunikation beenden) kannst du den jetzigen ThreadStart Delegaten durch einen ParameterizedThreadStart Delegaten ersetzen. Der hat einen object Parameter dessen Wert du beim Aufruf von Start() mitgeben kannst.

Für alle Dinge die in deiner ThreadProc Methode IDisposable implementieren (TcpClient, NetworkStream) solltest du über den using Syntax Dispose aufrufen. Dann wird auf wirklich immer aufgeräumt.

Moderiert von user profile iconTh69: C#-Tags hinzugefügt


tomycat - Fr 08.03.19 14:20


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
  private void button1_Click(object sender, EventArgs e)
        {

            Console.WriteLine("Button1 wurde gedrückt");

            Thread newThread = new Thread(Form1.ThreadProc);
            newThread.Start("42");

        //    Thread t = new Thread(new ThreadStart(ThreadProc));
         //   t.Start();
            Console.WriteLine("Los gehts");

        }

        public static void ThreadProc(object datax)
        {
          //  MessageBox.Show(datax.ToString());
            string server = "mein_server";
            string message = datax.ToString();
            try
            {
              
                Int32 port = 21;
                TcpClient client = new TcpClient(server, port);

                // Translate the passed message into ASCII and store it as a Byte array.
                Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

                // Get a client stream for reading and writing.
                //  Stream stream = client.GetStream();

                NetworkStream stream = client.GetStream();

                // Send the message to the connected TcpServer. 
                stream.Write(data, 0, data.Length);

                Console.WriteLine("Sent: {0}", message);

                // Receive the TcpServer.response.

                // Buffer to store the response bytes.
                data = new Byte[256];

                // String to store the response ASCII representation.
                String responseData = String.Empty;

                // Read the first batch of the TcpServer response bytes.
                Int32 bytes = stream.Read(data, 0, data.Length);
                responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
                Console.WriteLine("Received: {0}", responseData);
          
                // Close everything.
                stream.Close();
                client.Close();
            }
            catch (ArgumentNullException e)
            {
                Console.WriteLine("ArgumentNullException: {0}", e);
            }
            catch (SocketException e)
            {
                Console.WriteLine("SocketException: {0}", e);
            }

            Console.WriteLine("\n Press Enter to continue...");
            Console.Read();
        }


super Danke, letzte Frage. Ich möchte gerne responseData in die TextBox1 reinkopieren. Wie mache ich das am besten?


Ralf Jansen - Fr 08.03.19 14:43


C#-Quelltext
1:
TextBox1.Invoke((MethodInvoker)(() => { this.Text = responseData; }));                    


tomycat - Fr 08.03.19 16:23

hmmmm,
ich habe deine Code Zeile unter diese...

C#-Quelltext
1:
    Console.WriteLine("Received: {0}", responseData);                    

... gesetzt.

Leider macht er TextBox1 rot, sowie this.
Ich habe auch deinen Code anderen Stellen ausprobiert ohne Erfolg.


Delete - Fr 08.03.19 17:46

- Nachträglich durch die Entwickler-Ecke gelöscht -


Ralf Jansen - Fr 08.03.19 18:06

Zitat:
Ich möchte gerne responseData in die TextBox1 reinkopieren.


Zitat:
Leider macht er TextBox1 rot, sowie this.


Du hast in deinem Beitrag impliziert das es eine TextBox1 gibt. Wie heißt die den wirklich?

Möglicherweise ist auch einfach nur das Problem das du dein ThreadProc Methode statisch gemacht hast. Sobald du auf Instanzdaten zugreifen willst darf die nicht mehr statisch sein.


tomycat - Sa 09.03.19 13:45

Irgendwie habe ich den Faden verloren. Ich habe von der Toolbox eine TextBox herausgezogen und in die FORM1 gesetzt. Visual Studio hat dann daraus TextBox1 erstellt.


tomycat - So 10.03.19 22:09

sorry, ich steige da nicht durch.

Ich habe aus:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
//vorher
public static void ThreadProc(object datax)
//nachher
public void ThreadProc(object datax)

//vorher
Thread newThread = new Thread(Form1.ThreadProc);
//nachher
Thread newThread = new Thread(ThreadProc);


// neu im Thread:
TextBox1.Invoke((MethodInvoker)(() => { this.Text = responseData; }));


Leider bleibt die TextBox1 leer.

Bin für jeden Tip Dankbar


Ralf Jansen - So 10.03.19 23:14

Ersetze this.Text durch TextBox1.Text.


tomycat - Di 12.03.19 09:57

Leider ist noch ein Problem aufgetreten...

Es ist ja so, ich sende ein Datenpacket und warte auf eine Antwort, aber passiert wenn ich keine Antwort bekomme?

Wie könnte es schaffen, dass ich mehrere Packete sende und mein Prog wartete immer ca.2 sec und eine Antwort? Sprich warte immer 2 sec., wenn keine Antwort kommt, sende das nächste Packet.


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
for(int a = 0; a < anzahl_der_Packete;a++)
{
  send packet[a];

  try // warte 2 Seckunden
  {
     // schnipp
                Int32 bytes = stream.Read(data, 0, data.Length);
                responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
                Console.WriteLine("Received: {0}", responseData);
      //schnipp
  }
}


Th69 - Di 12.03.19 10:54

Die Antwort ist immer noch dieselbe: asynchrone Programmierung, z.B. mittels Task.Delay(2000) [https://docs.microsoft.com/de-de/dotnet/api/system.threading.tasks.task.delay?view=netframework-4.7.2]!


tomycat - Fr 15.03.19 12:11

thx,
ich bin deinen Rat nachgegangen und habe Paraell gegooglt...

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
public partial class Form1 : Form
    {
        String server = "111.222.3.4";
        Int32 port = 666;
        TcpClient client;
        NetworkStream stream;

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
           client = new TcpClient(server, port);
           stream = client.GetStream();

            var t = Task.Run(async delegate
            {
                meinsender("test1");
                await Task.Delay(1000);
                return 42;
            });

            t.Wait();
             t = Task.Run(async delegate
            {
                meinsender("test2");
                await Task.Delay(1000);
                return 42;
            });
            t.Wait();

            t = Task.Run(async delegate
            {
                meinsender("test3");
                await Task.Delay(1000);
                return 42;
            });
            t.Wait();
            stream.Close();
            client.Close();
        }
        public async Task meinsender(string nachricht)
        {
            MessageBox.Show(nachricht);
            Byte[] data = System.Text.Encoding.ASCII.GetBytes(nachricht);
           
            stream.Write(data, 0, data.Length);
            Console.WriteLine("Sent: {0}", nachricht);

            data = new Byte[256];
            String responseData = String.Empty;
            Int32 bytes = stream.Read(data, 0, data.Length);
            responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
            Console.WriteLine("Received: {0}", responseData);
        }
    }


Also,
test1 ging durch und ich habe eine Antwort bekommen. Die Meldung test2 wurde angezeigt, nach Enter blockiert das Programm.
Das Programm hat nur ein Button. Ich will test1 test2 und test3 senden. Bin für jeden Tip dankbar.


jfheins - Fr 15.03.19 13:59

Du kannst im TclpClient die ReceiveTimeout Property [https://docs.microsoft.com/en-us/dotnet/api/system.net.sockets.tcpclient.receivetimeout?view=netframework-4.7.2] setzen. Damit sollte dein Lesevorgang abgebrochen werden, wenn nichts empfangen wird.

Was du aktuell machst: Etwas empfangen (ggf. unendlich lange darauf warten) und dann noch 1 Sekunden warten. Das macht nicht so viel Sinn ...

Rein aus dem Kopf hätte ich so etwas versucht:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
public async Task<string> reveiveWithTimeout(TcpClient client, int timeOut, int byteCount)
{
    client.ReceiveTimeout = 5000;
    try
    {
        data = new Byte[byteCount];
        Int32 bytes = client.GetStream().Read(data, 0, byteCount);
        var responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
        Console.WriteLine("Received: {0}", responseData);
        return responseData;
    }
    catch (IOException)
    {
        return null;
    }
}


tomycat - Fr 15.03.19 14:53

Ich habe die sende/empfangs Funktion so umgebaut, wenn du meinst es wäre Käse, dann erstelle ich eine Funktion für senden und eine für Empfang:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
 public async Task meinsender(string nachricht)
        {
            MessageBox.Show(nachricht);
            Byte[] data = System.Text.Encoding.ASCII.GetBytes(nachricht);
           
            stream.Write(data, 0, data.Length);
            Console.WriteLine("Sent: {0}", nachricht);
            /*
            data = new Byte[256];
            String responseData = String.Empty;
            Int32 bytes = stream.Read(data, 0, data.Length);
            responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
            Console.WriteLine("Received: {0}", responseData);
            */

            client.ReceiveTimeout = 2000;
         //   try
         //   {
                data = new Byte[200];
                Int32 bytes = client.GetStream().Read(data, 0200);
                var responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
                Console.WriteLine("Received: {0}", responseData);
             //   return responseData;
         
        }

Zum testen habe ich mal mein ftp Server genommen.
die Ausgabe vom Visual Studio:


HTML-Dokument
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
Sent: test1
Received: 220 FTP Server ready.

Sent: test2
Ausnahme ausgelöst: "System.Net.Sockets.SocketException" in System.dll
"mein-pro-idee2.vshost.exe" (CLR v4.0.30319: mein-pro-idee2.vshost.exe): "C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.resources\v4.0_4.0.0.0_de_b77a5c561934e089\System.resources.dll" geladen. Das Modul wurde ohne Symbole erstellt.
Ausnahme ausgelöst: "System.IO.IOException" in System.dll
Sent: test3
Ausnahme ausgelöst: "System.Net.Sockets.SocketException" in System.dll
Ausnahme ausgelöst: "System.IO.IOException" in System.dll
Der Thread 0x7c0 hat mit Code 0 (0x0) geendet.
Der Thread 0x1b0c hat mit Code 0 (0x0) geendet.
Der Thread 0x1a00 hat mit Code 0 (0x0) geendet.
"mein-pro-idee2.vshost.exe" (CLR v4.0.30319: mein-pro-idee2.vshost.exe): "C:\Windows\Microsoft.Net\assembly\GAC_MSIL\mscorlib.resources\v4.0_4.0.0.0_de_b77a5c561934e089\mscorlib.resources.dll" geladen. Das Modul wurde ohne Symbole erstellt.
Der Thread 0xd4c hat mit Code 0 (0x0) geendet.


Der ftp Server muss doch nach den User fragen oder?


jfheins - Fr 15.03.19 17:14

Zunächst: Die SocketException zeigt dir ja an, dass es zu einem Timeout kommt.

Über die Gründe kann ich (mangels FTP Server) gerade nur spekulieren.

Wenn ich zum Beispiel das hier anschaue [https://forums.digitalpoint.com/threads/help-me-filezilla-ftp-server-login-problem.2035299/] Müsstest du nach dem 220 vom Server direkt einen Befehl schicken, der mit "USER " anfängt :wink:

Ich glaube, wenn du einen FTP Befehl schickt, musst du auch ein Zeilenende hinterher schicken.


tomycat - So 17.03.19 12:32

Mein komplette Quelltext von mir stand der Dinge...

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
public partial class Form1 : Form
    {
        String server = "***.***.**.***."// mein ftpServer
        Int32 port = 21//vorerst zum testen
        TcpClient client;
        NetworkStream stream;
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            client = new TcpClient(server, port);
            stream = client.GetStream();
            meinempfaenger();
            MessageBox.Show("moment");
            var t = Task.Run(async delegate
            {
                meinsender("USER");
                meinempfaenger();
                await Task.Delay(1000);
                return 42;
            });
            t.Wait();
            t = Task.Run(async delegate
            {
                meinsender("PASS");
                meinempfaenger();
                await Task.Delay(1000);
                return 42;
            });
            t.Wait();
            t = Task.Run(async delegate
            {
                meinsender("test3");
                meinempfaenger();
                await Task.Delay(1000);
                return 42;
            });
            t.Wait();
            stream.Close();
            client.Close();
        }
        public async Task meinsender(string nachricht)
        {
            MessageBox.Show(nachricht);
            Byte[] data = System.Text.Encoding.ASCII.GetBytes(nachricht);
            stream.Write(data, 0, data.Length);
            Console.WriteLine("Sent: {0}", nachricht);     
        }
        public async Task meinempfaenger()
        {
            Byte[] data = System.Text.Encoding.ASCII.GetBytes("");
            client.ReceiveTimeout = 2000;
            data = new Byte[200];
            Int32 bytes = client.GetStream().Read(data, 0200);
            var responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
            Console.WriteLine("Received: {0}", responseData);
        }
    }


Die Ausgabe


HTML-Dokument
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
Received: 220 FTP Server ready.

"Idee2.vshost.exe" (CLR v4.0.30319: Idee2.vshost.exe): "C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\mscorlib.resources\v4.0_4.0.0.0_de_b77a5c561934e089\mscorlib.resources.dll" geladen. Das Modul wurde ohne Symbole erstellt.
Sent: USER
"Idee2.vshost.exe" (CLR v4.0.30319: Idee2.vshost.exe): "C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.resources\v4.0_4.0.0.0_de_b77a5c561934e089\System.resources.dll" geladen. Das Modul wurde ohne Symbole erstellt.
Ausnahme ausgelöst: "System.IO.IOException" in System.dll
Sent: PASS
Ausnahme ausgelöst: "System.IO.IOException" in System.dll
Sent: test3
Ausnahme ausgelöst: "System.IO.IOException" in System.dll
Der Thread 0x2c90 hat mit Code 0 (0x0) geendet.
Der Thread 0x2498 hat mit Code 0 (0x0) geendet.


Vom Prinzip her möchte ich nur einen einfachen TCP CLient der sich mit einem Port verbindetet und Nachrichten versedet/empfängt.
Zum testen habe ich meinem FTP genommen. Ob ich jetzt USER oder etwas anderes sende, der FTP Server will nicht mit mir reden.
Ich hätte nie gedacht dass das so schwer ist. Egal ob ich nach der Verbindung erst sende oder etwas empfange, es will nicht. :-(


jfheins - Mo 18.03.19 08:17

Versuche den Anfang mal so:

C#-Quelltext
1:
2:
3:
4:
5:
6:
           var t = Task.Run(async delegate
            {
                meinempfaenger();
                meinsender("USER x \r\n");
                await Task.Delay(100);
            });

Mit Zeilenumbruch ;-)


tomycat - Mo 18.03.19 09:33

genau so ist es.thx


Christian S. - Mo 18.03.19 14:52

Noch ein Hinweis: Wenn Du mit async und await arbeiten willst, dann solltest Du es auch "richtig" tun. Auf eigentlich asynchrone Methoden mit einem Aufruf von Wait zu warten, kann zu einem Deadlock führen: http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

Du kannst die Event-Handler z.B. als

C#-Quelltext
1:
private async void button1_Click(object sender, EventArgs e)                    

deklarieren und dann darin await verwenden. Dann kannst Du die einzelnen Aufrufe von Task.Run vollständig auflösen in einen "normalen" Quelltext.



//edit: bzw. solltest Du generell mal schauen, wofür Du async / await bei Dir überhaupt brauchst, ich sehe da bis auf Task.Delay keinen asynchronen Aufruf und den kann mit Thread.Sleep ersetzen ...


tomycat - Di 19.03.19 13:16

THX,

ich habe ein anderes Problem bekommen, wie kann ich in der Funktion einen Text in eine Textbox ausgeben?


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
 public async Task meinsender(string nachricht)
        {
            MessageBox.Show(nachricht);
            Byte[] data = System.Text.Encoding.ASCII.GetBytes(nachricht);
            stream.Write(data, 0, data.Length);
            Console.WriteLine("Sent: {0}", nachricht);     
        }


Console.WriteLine geht ohne Probleme.

C#-Quelltext
1:
textBox1.Invoke((MethodInvoker)(() => { textbox1.Text = responseData; }));  // was muss ich hier ändern?                    


jfheins - So 24.03.19 14:00

user profile icontomycat hat folgendes geschrieben Zum zitierten Posting springen:
THX,

ich habe ein anderes Problem bekommen, wie kann ich in der Funktion einen Text in eine Textbox ausgeben?


Das geht am besten, indem du den Rat von Christian beherzigst ;-)
Diese IO Methoden bieten in der Regel eine Async() Methode an. Damit wartet der Hauptthread deines Programms auf die Antwort vom Server, kann aber zwischendurch trotzdem auf Benutzereingaben reagieren. (vgl: https://docs.microsoft.com/de-de/dotnet/csharp/programming-guide/concepts/async/)

Für deinen Code könnte das in etwa so aussehen:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
private async void button1_ClickAsync(object sender, EventArgs e)
{
    client = new TcpClient(server, port);
    stream = client.GetStream();

    textbox1.Text = await ReceiveString(stream);

    await SendString(stream, "USER x \r\n");

    textbox1.Text = await ReceiveString(stream);
}

public async Task SendString(NetworkStream stream, string nachricht)
{
    byte[] data = System.Text.Encoding.ASCII.GetBytes(nachricht);
    await stream.WriteAsync(data, 0, data.Length);
}

public async Task<string> ReceiveString(NetworkStream stream, int timeout = 1000)
{
    stream.ReadTimeout = timeout;
    var data = new byte[200];
    int receivedBytes = await stream.ReadAsync(data, 0200);
    return System.Text.Encoding.ASCII.GetString(data, 0, receivedBytes);
}

Du siehst, mit await wird der Code sehr viel "linearer" und dadurch lesbarer. Einen Task<string> kannst du als Aktion verstehen, die in Zukunft einen string zurückliefert. Mit await unterbrichst du den Thread und wartest genau darauf, dass das passiert.

Ganz wichtig: Die Wiederaufnahme passiert in der Regel im gleichen Thread, daher benötigst du keinerlei .Invoke( oder so.