Datenweitergabe
-
Hallo,
ich habe einen kleinen Server, der wartet, bis er bestimmte Daten bekommen hat.
public class Server { public int port { get; set; } private TcpListener tcpListener; private Thread listenerThread; private RemoteDataDelivery data; public Server(int port) { this.port = port; } public void AddDataSource(RemoteDataDelivery d) { data = d; } // start server public void Start() { tcpListener = new TcpListener(new IPEndPoint(IPAddress.Any, port)); tcpListener.Start(); // start tcp listener listenerThread = new Thread(new ThreadStart(Listener)); listenerThread.Start(); } // stop server public void Stop() { tcpListener.Stop(); listenerThread.Abort(); } private void Listener() { while (true) { try { TcpClient client = tcpListener.AcceptTcpClient(); new Thread(new ThreadStart(() => HandleClient(client))).Start(); } catch (Exception ex) { Console.WriteLine("Error in listener thread."); Console.WriteLine(ex.Message); } } } private void HandleClient(TcpClient client) { PACKET_ID id = ReadPacketID(client); switch (id) { case PACKET_ID.FIELD_REQUEST: // field on local map is requested //... break; case PACKET_ID.PLAYER_MOVED: data.PlayedMovedNotification(ReadTuple(client), ReadTuple(client)); break; case PACKET_ID.DISCONNECTED: // another played disconnected //... break; // Wie kriege ich am besten diese Daten zurück an meine GUI? case PACKET_ID.PLAYER_JOINT: // a new player int numOfPlayer = ReadInt(client); for (int i = 0; i < numOfPlayer; i++) { Console.WriteLine("ID " + ReadInt(client)); Console.WriteLine("IP " + ReadIP(client)); Console.WriteLine(""); } byte[] res = BitConverter.GetBytes((int)PACKET_ID.ACK); client.GetStream().Write(res, 0, res.Length); break; default: throw new ArgumentException("No such option!"); } client.Close(); } //...
Der Server wird in einem Formular benutzt:
public partial class ClientWindow : Form { // server for accepting new player private int port = 1556; private Server server; public ClientWindow() { InitializeComponent(); server = new Server(port); server.Start(); } //....
Problem: Ich weiß nicht, wie ich am geschicktesten die Daten, die in PACKET_ID.PLAYER_JOINT momentan einfach auf der Konsole ausgebe, wieder zurück an die Form gebe. In diesem Thread (http://www.c-plusplus.net/forum/325428) habe bereits einen Lösungsanstz erhalten, den ich auch umgesetzt habe. Sobald in Daten anfallen, wird die RemoteDataDelivery Instanz aufgerufen. Doch kann ich ein Formular nicht das Interface RemoteDataDelivery implementieren lassen. Allgemein kommt mir das noch sehr gefrickelt vor.
Wie löse ich mein Problem am elegantesten? Soll ich etwa für jeden Case-Fall ein eigenes Event auslösen, das dann je eigene EventArgs hat?
Danke
-
Ja, am besten mittels eigenen Events. Ob du aber verschiedene Events bereitstellst, oder aber nur ein Event und passende EventArgs (die dann der Benutzercode interpretieren muß), mußt du selber für dich entscheiden.
Aber zuerst einmal solltest du dir eine passende Datenklasse für die Spieldaten entwickeln (die unabhängig von der GUI sein sollte). Dann brauchst du für die GUI nur eine Benachrichtigungssystem (Notification), so daß die GUI dann einfach auf die Instanz der Datenklasse lesend zugreifen kann.
-
Th69 schrieb:
Ja, am besten mittels eigenen Events. Ob du aber verschiedene Events bereitstellst, oder aber nur ein Event und passende EventArgs (die dann der Benutzercode interpretieren muß), mußt du selber für dich entscheiden.
ok. danke
Th69 schrieb:
Aber zuerst einmal solltest du dir eine passende Datenklasse für die Spieldaten entwickeln (die unabhängig von der GUI sein sollte). Dann brauchst du für die GUI nur eine Benachrichtigungssystem (Notification), so daß die GUI dann einfach auf die Instanz der Datenklasse lesend zugreifen kann.
Du meinst eine Klasse, die hier die ID und die IP kapselt? Eine Instanz würde dann der Server erstellen und über die Notification verschicken. Die GUI würde die dann bekommen. Meinst Du das?
-
Ja schon eine eigene Klasse. Aber ich weiß nicht, wie umfangreich deine Daten sind. M.E. wäre es besser du würdest eine unabhängige "Datenmanager"-Klasse haben, welche sowohl von deiner Klasse Server (die ja eher ein Client darstellt!) als auch der GUI angesprochen werden kann.
Am besten sollte die GUI deine Server-Klasse auch gar nicht kennen, sondern beide kennen nur jeweils die Daten (bzw. den Datenmanager).
Und die Events würden dann jeweils von der Datenmanager-Klasse ausgelöst (getriggert).Graphisch also in etwas so:
Server (Client) <--> Datenmanager <--> GUIVersuche beim Design möglichst immer das "Single Responsible Principe" sowie "Separation of Concerns" zu beachten!
-
Alles klar. An solch eine Datenmanager Klasse hatte ich auch schon gedacht, aber in meinem konkreten Fall geht es tatsächlich nur um die IP Adresse und um die ID, also eine "IPAddress" und um einen int. Da schätze ich eine eigene Klasse eher als Overkill ein, auch wenn damit schön Seperation on Concerns erfüllt würde. Diese Klasse würde nichts anderes machen, als das Event, welches vom Server getriggert wurde, weiterzutriggern und schließlich der GUI zu sagen, dass diese nun über siedie Daten vom Server holen kann.
Wären es mehr Daten oder müssten diese noch verarbeitet werden, dann würde ich deinen Plan sofort umsetzen.
Thx a lot