Backgroundworker kann durch Socket nicht beendet werden
-
Du musst das Accept() in einer Schleife laufen lassen, also Lösung b).
Das werde ich mal versuchen.
Aber was meinst du mit
Du kannst dann über Events eine "Schleife" bauen.
???
Gruß
-
Das sieht ungefähr so aus (ungetestet, sollte als Beispiel aber genügen):
using System; using System.Data; using System.Text; using System.Windows.Forms; using System.Net; using System.Net.Sockets; namespace Server { public partial class ServerForm : Form { Socket serverSocket; byte[] byteData = new byte[1024]; public ServerForm() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { try { serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 1000); serverSocket.Bind(ipEndPoint); serverSocket.Listen(4); // Hier der asynchrone Aufruf serverSocket.BeginAccept(new AsyncCallback(OnAccept), null); } catch (Exception ex) { // ignore } } private void OnAccept(IAsyncResult ar) { try { Socket clientSocket = serverSocket.EndAccept(ar); // Hier findet die "Schleife" ihre Anwendung und zwar durch rekursiven Aufruf von BeginAccept() serverSocket.BeginAccept(new AsyncCallback(OnAccept), null); clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnReceive), clientSocket); } catch (Exception ex) { } } private void OnReceive(IAsyncResult ar) { try { Socket clientSocket = (Socket)ar.AsyncState; clientSocket.EndReceive(ar); // Datan verarbeiten ... // Und wieder durch rekursiven Aufruf weitere Daten empfangen clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnReceive), clientSocket); } catch (Exception ex) { } } } }
-
Hallo
Da das Ganze ja dauerhaft laufen soll habe ich folgenden Code nun innerhalb einer while(true) Schleife im BGW laufen lassen.
// Hier der asynchrone Aufruf serverSocket.BeginAccept(new AsyncCallback(OnAccept), null);
Ausführen kann ich den code. Aber die OnAccept Methode wird nur ein einziges mal beim starten aufgerufen. Danach nicht mehr. Auch wenn der Client weiterhin Daten sendet.
Gruß
-
BeginAccept() dient dazu die Verbindung des Clients zu akzeptieren, mehr nicht. Um Daten vom Client empfangen zu können, benötigst du Begin-/EndReceive() (siehe mein Beispiel oben). Wenn du dich für asynchrone Aufrufe entscheidest, dann ist der BackgroundWorker überflüssig, das ist ja gerade der Vorteil.
- Willst du an deinem bestehenden Code nicht viel Ändern, dann bleib beim BGW, setzt das Accept() in eine Schleife und führ das Receive solange aus, bis vom Client alle Daten abgeholt wurden
- Willst du asynchron arbeiten, kann der BGW weg und du musst wie in meinem Beispiel vorgehen. (Einfach mal nach googlen)
-
Hi
Ja, soweit (eigentlich) so klar. Ich war eben etwas voreilig mit Copy/Paste.
Prinzipiell möchte ich gerne die Asynchrone Variante verwenden. Jedoch soll das gnaze nicht beim starten der Applikation angetriggert werden, sondern ich möchte mit einem Start und Stop Button das empfangen starten und stoppen.
Wäre es daher sinnvoll die Verbindung wie in deinem Beispiel zu akzeptieren und dann in einem BGW die Daten zu empfangen?
Gruß
-
Nein wäre es nicht. BeginXXX/EndXXX bringen ja den Vorteil, das das UI davon unbehelligt bleibt, da diese Methoden im Threadpool einen eigenen Thread anlegen. Um dem UI Änderungen zu vermitteln, musst du dann Dispatcher.Invoke() aufrufen.
Du kannst den Code aus der Form_Loaded-Methode auch einfach in die Click-Methode des Start-Buttons einbauen.
-
Hallo
U.a. habe ich mir mal folgenden Link angeschaut:
http://msdn.microsoft.com/de-de/library/bbx2eya8(v=vs.80).aspxIch glaube (hoffe) das Ganze so langsam zu verstehen. Benutze ich BeginnXXX/EndXXX wird der Callback in einem extra Thread bearbeitet. Benutze ich den BGW wäre das Doppelt gemoppelt.
Morgen werde ich das ganze nochmals programmiertechnisch umzusetzen.
Bei meiner Recherche bin ich auch auf folgenden Link gestoßen: http://www.codeplanet.eu/tutorials/csharp/4-tcp-ip-socket-programmierung-in-csharp.html?start=2
Ist es zu empfehlen TcpClient und TcpListener zu verwenden?
-
Hallo
Also ein Stück bin ich nun weiter.
Ich habe mal folgendes versucht umzusetzen. Das ist ähnlich wie mir vorher geraten wurde. Prinzipiell funktionierts auch, jedoch wird durch die while(true) schleife meine Form blockiert.Wie kann ich das denn umgehen bzw verhindern?
Anbei mal der Code:
private void button1_Click(object sender, EventArgs e) { StateObject myFinalStateobject = new StateObject(); IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any , myPort); Socket mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); StartListening(ipEndPoint); } public void StartListening(IPEndPoint localEP) { Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); listener.Bind(localEP); listener.Listen(10); // Diese Schleife macht das Problem while (true) { allDone.Reset(); listener.BeginAccept(new AsyncCallback(acceptCallback), listener); if (allDone.WaitOne(2000)) { SetTextRecieveLog("Verbindung Erfolgreich aufgebaut! "); } else { SetTextRecieveLog("Timeout Verbindungsaufbau" + localEP.ToString()); } } } public void acceptCallback(IAsyncResult ar) { allDone.Set(); Socket listener = (Socket)ar.AsyncState; Socket handler = listener.EndAccept(ar); // Additional code to read data goes here. // Create the state object. StateObject state = new StateObject(); state.workSocket = handler; handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(readCallback), state); }
-
Nun auch als Mitglied......
-
Mach die Schleife weg und ruf in acceptCallback() nochmals BeginAccept() auf. So erzeugst du wiederholtest die Abfrage von Client-Verbindungen.
-
Hi
Mach die Schleife weg und ruf in acceptCallback() nochmals BeginAccept() auf. So erzeugst du wiederholtest die Abfrage von Client-Verbindungen.
Die Lösung funktioniert leider nicht.
Mitlerweile habe ich es hinbekommen.
Den Socket habe ich doch schon. Daher muss ich doch irgendwie fortlaufend die BeginnReceive Methode aufrufen-Jedoch finde ich das das nicht so ne ganz saubere Lösung ist da meine Lösung eher Zeitgesteurt und nicht Ereignisgesteuert ist.
Irgendwie muss es doch möglich sein die BeginnReceive Methode aufzurufen, direkt nach dem Daten empfangen wurden??? Ich habs schon mit
receiveDone.WaitOne
() versucht, aber das hat auch nicht funktioniert....
Hier mal die zeitgesteuerte Lösung:
public void acceptCallback(IAsyncResult ar) { allDone.Set(); Socket listener = (Socket)ar.AsyncState; Socket handler = listener.EndAccept(ar); // Additional code to read data goes here. // Create the state object. listener.BeginAccept(new AsyncCallback(acceptCallback), listener); StateObject state = new StateObject(); state.workSocket = handler; while (true) { receiveDone.Reset(); handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(readCallback), state); Thread.Sleep(1000); if (myState.sb.ToString() != "") SetTextRecieveLog(myState.sb.ToString()); myState.sb.Clear(); } }
-
Hi
Da ich noch immer nicht so richtig weiter komme möchte ich meine Frage mal etwas konkreter stellen:
Folgender Code:
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(readCallback), state);
Wenn ich das richtig verstanden habe wird doch readCallback nur aufgerufen nachdem wirklich Daten vom Client empfangen wurden? Oder nicht?
Bei mir wird diese Funktion ständig aufgerufen wenn ich ein schleife um BeginRecieve mache...