Entwickler-Ecke

Basistechnologien - Mit Socket-Client senden und empfangen


sipungora - Mi 20.10.10 13:07
Titel: Mit Socket-Client senden und empfangen
Hi,

es geht um die Klient-Programmierung.
Frage 1:
Wenn ich ein Socket im Konstruktor erzeuge und in sendMessage() oder receiveMessage() ihn benutze dann funkzioniert dass nur ein mal und beim zweiten Senden kommt es zur Exception. Muss ich also immer ein neues Socket zu erzeugen, wenn ich ne neue Message senden möchte?
Etwa so:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
                        Socket client = new (endPoint.AddressFamily,
                           SocketType.Stream, ProtocolType.Tcp);
                        //---connect to the server---
                        client.Connect(endPoint);

                        //---send the data---
                        byte[] data = ASCIIEncoding.ASCII.GetBytes(msg);
                        client.Send(data);
                        client.Close();

Oder gibt's Möglichkeit ihn doch ein mal zu erzeugen und dann später mehrmals zu benutzen?

Frage 2:
Mein Server ist in Java umgesetzt. Wenn ich ihn mit Java-Client teste, dann läuft alles einbandfrei. Wenn ich C#-Client benutze, dann senden funktioniert, aber wird nichts empfangen. Beim Empfangen sieht das Ablauf so aus. Zuerst sende ich an den Server ein Kommando, dann sendet mir der Server eine Antwort. Mein code fürs Empfangen:


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:
            public string receiveMessage(string command)
            {
                string stringData = null;
                    try
                    {
                        Socket client = new Socket(endPoint.AddressFamily,
                           SocketType.Stream, ProtocolType.Tcp);
                        //---connect to the server---
                        client.Connect(endPoint);

                        //---send the data---
                        byte[] data = ASCIIEncoding.ASCII.GetBytes(command);
                         client.Send(data);
                         client.Close();

                         client = new Socket(endPoint.AddressFamily,
                            SocketType.Stream, ProtocolType.Tcp);
                         //---connect to the server---
                        client.Connect(endPoint);
                        data = new byte[1024];
                        int receivedDataLength = client.Receive(data);
                        stringData = Encoding.ASCII.GetString(data, 0, receivedDataLength);
                        client.Close();
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                return stringData;
            }


Was mache ich falsch? Hab ich meine receive-Methode "optimal" umgesetzt? Ich bin nicht mit c#-Richtlinien bzgl. Socket-Programmierung vertraut.

Vielen Dank im Voraus.

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


huuuuuh - Mi 20.10.10 13:37

zu Frage 1: Mehrmals senden mit einem Socket geht. Frag mich bitte nicht, wie^^ wie sieht denn die Exception aus?
zu Frage 2: Das Problem dabei ist, dass immer etwas "empfangen" wird, selbst wenn nichts da ist. d.h., das empfangene ist leer. Denn die Antwort ist ja nicht sofort da, sondern braucht nen paar Millisekunden zum Server und zurück. Direkt nach dem senden ist die Antwort noch nicht da, das empfangene also leer.
Du hast jetzt 2 Möglichkeiten:
*Thread.Sleep(); nutzen, um nach dem senden kurz zu warten.
*Das empfangen in einer Schleife ablaufen lassen und warten bis etwas da ist. Schlägt allerdings ziemlich auf die CPU-Auslastung.

Oder du arbeitest mit dem TcpClient und NetworkStream... (was eine ganz andere, 3. Möglichkeit wäre)


sipungora - Mi 20.10.10 14:32

user profile iconhuuuuuh hat folgendes geschrieben Zum zitierten Posting springen:
zu Frage 1: Mehrmals senden mit einem Socket geht. Frag mich bitte nicht, wie^^ wie sieht denn die Exception aus?
zu Frage 2: Das Problem dabei ist, dass immer etwas "empfangen" wird, selbst wenn nichts da ist. d.h., das empfangene ist leer. Denn die Antwort ist ja nicht sofort da, sondern braucht nen paar Millisekunden zum Server und zurück. Direkt nach dem senden ist die Antwort noch nicht da, das empfangene also leer.
Du hast jetzt 2 Möglichkeiten:
*Thread.Sleep(); nutzen, um nach dem senden kurz zu warten.
*Das empfangen in einer Schleife ablaufen lassen und warten bis etwas da ist. Schlägt allerdings ziemlich auf die CPU-Auslastung.

Oder du arbeitest mit dem TcpClient und NetworkStream... (was eine ganz andere, 3. Möglichkeit wäre)


Danke schön, huuuuuh.

Meine Exception lautet "Make sure you have not released a resource before attempting to use it". Das kann man dadurch lösen, dass man am Ende keine socket.Close() macht. Aber so wird meine Verbindung immer geöffnet und ich möchte das nicht. In der Beschreibung zur Close() steht, dass dadurch geöfnete Verbindung geschlossen wird und alle Resources befreit werden. Welche Methode kann ich danach aufrufen damit man mit dem bestehenden Socket eine neue Verbindung aufbauen kann? Ich habe probiert Bind(endPoint). Das hat nix gebracht.

Ich habe es mit dem Empfang nicht ganz verstanden. Bei mir passiert das Folgendes. Wenn die Zeile

int receivedDataLength = client.Receive(data);

erreicht wird, weiter passiert nichts. Du sagst, dass
Zitat:
immer etwas "empfangen" wird
Wieso läuft mein Programm dann nicht weiter mit receivedDataLength = 0?

Wenn ich das mit der Schleife realisiere, wie kann ich dann das Empfang testen, wenn client.Receive(data) blockiert wird?

Für Thread.Sleep() hab ich 30*1000 ms gesetzt. Das Ergebnis war gleich. Es wird beim Receive blockiert.
(Sleep rufe ich vor Receive.)

Nun probiere ich TcpClient.


huuuuuh - Mi 20.10.10 14:58

Das Receive blockiert? dann hab ich wohl was falsch gemacht, als ich mal probiert hab was mit sockets zu machen ^^
Dann vergiss alles, was ich gesagt hab, war wahrscheinlich falsch . . . :wink:


Kha - Mi 20.10.10 22:07

Normalerweise gilt: Ein Thread, eine Frage, aber da hier anscheinend beide aufs gleiche hinauslaufen: Beim Empfangen einer Antwort würde ich auf keinen Fall eine neue Connection öffnen, schließlich könnte diese erst nach dem Erhalt der Nachricht überhaupt aufgebaut sein. Solltest du einen Socket trotzdem schließen, wenn du gerade keine Antwort erwartest, brauchst du zum Wieder-Öffnen auch eine neue Socket-Instanz.