Ich versuche einen Server mit TCPChannels zu realisieren. Der Server soll Daten von mehreren Client bekommen, sowie Daten an bestimmte Clients senden. Die Clients werden auch von mir mit TCPChannels erstellt.
Mein Problem ist, dass die Kommunikation mit einem Port bzw. einem Client funktioniert. Senden und Enfangen funktioner in beide Richtungen.
Öffene ich mehere Client mit verschiedenen Ports, kann ich vom Server aus keinen definierten Client ansprechen. Es wird, so wie ich es sehe, vom Server immer der letzte registrierte Port angesprochen.
Meine Idee war, dass ich mir alle relelvanten Daten in einer Liste speichere. Zum Senden nehme ich dann den entsprechenden Eintrag.
Irgendwie komme ich nicht weiter, mir gehen die Ideen aus. Ist die Idee im Ansatz überhaupt richtig oder wie kann man sowas lösen?
Hier mal der Code für den Server, der für jeden Port ausgeführt wird.
Die Listenverwaltung ist hier nicht zu sehen.
private void InitServerChannel()
{
TcpChannel _ServerChannel;
BinaryServerFormatterSinkProvider _provider;
ClientComms _ClientComms;
try
{
int Port = 1001;
// Creating a custom formatter for a TcpChannel sink chain.
_provider = new BinaryServerFormatterSinkProvider();
_provider.TypeFilterLevel = TypeFilterLevel.Full;
_ClientComms = new ClientComms();
// Creating the IDictionary to set the port on the channel instance.
IDictionary props = new Hashtable();
props["port"] = Port;
props["name"] = string.Format("tcp{0}", Port);
// Pass the properties for the port setting and the server provider
_ServerChannel = new TcpChannel(props, null, _provider);
ChannelServices.RegisterChannel(_ServerChannel, false);
// Create the server object for clients to connect to
RemotingConfiguration.RegisterWellKnownServiceType(typeof(ClientComms), "RemoteServer", WellKnownObjectMode.Singleton);
ClientComms.MessageFromClientHandler += OnMessageFromClient;
}
catch (Exception ex)
{
Log(ex.Message);
}
}
private void Send()
{
DataStructureServer data = new DataStructureServer(1, "Message from Server");
_ClientComms.FireNewBroadcastedMessageEvent(data);
}
Und hier der clientseitige Code
private void InitClientChannel(object sender, EventArgs e)
{
try
{
// Use a defined port to receive callbacks or 0 to receive available port
_ClientChannel = new TcpChannel(0);
ChannelServices.RegisterChannel(_ClientChannel, false);
// Create the object for calling into the server
string url = "tcp://127.0.0.1:1001/RemoteServer";
_RemoteObject = (ServerComms)Activator.GetObject(typeof(ServerComms), url); // Must match IP and port on server
// Define sink for events
RemotingConfiguration.RegisterWellKnownServiceType(typeof(NotifySink), "ServerEvents", WellKnownObjectMode.Singleton);
_sink = new NotifySink();
// zuweisen der Callback funktion zum Empfang der Server daten
// Falls der Server nicht gestartet ist, ist
_RemoteObject.Notify += new NotifyCallback(_sink.FireNotifyCallback);
// Weiterleiten der Serverdaten über die Callbackfunktion zum Messagehandler
_sink.MessageFromServerHandler += MessageFromServer;
Log("Connected to "+ url);
}
catch(Exception ex)
{
Log(ex.Message);
}
}
Beschreibe mal genau, was Du erreichen willst. Vom ersten Eindruck her verstehst Du das Protokoll nicht.
Das TCP-Protokoll baut auf dem IP-Protokoll auf. Und bei IP sind die EndPoints immer Host + Port. Eine TCP-Verbindung besteht aus Client IP und Client Port (Client-Endpoint) + Server IP und ServerPort (Server-Endpoint) + dem Protokoll TCP.
Der TCP Channel ist nur ein Wrapper um die Funktionen aus socket.h.
Erreichen möchte ich, dass der Server eine Kommunkation zu verschiedenen Clients aufnimmt. Es sollen Datenstrukturen übertragen werden. Dazu möchte ich am Server entscheiden, welcher Client die Daten bekommen soll.
Das mit dem Client- und Serverendpoint ist schon klar. Ich brauche im Server nur mehrere ServerEndpoints, wobei sich jeder mit einem andere Client verbindet. Da möchte ich erreichen.
Du hast schon recht, den richtigen Durchblick bei TCPChannels habe ich nocht nicht. Ich hatte vor diversen Jahren mal Sockets programmiert, das ist aber auch schon alles.
Ich würde an Deiner Stelle entweder direkt Sockets nehmen und entweder JSON oder Protocol Buffer für die Serialisierung oder WCF.
Remoting ist eine sehr veraltete Technologie, die man nur nimmt, wenn man muss.
Du kannst die Low-Level Details von Remoting auch einfach umgehen indem du ein Framework verwendest das den Job für dich übernimmt.
Dafür bietet sich das Remoting Framework Zyan mehr als an.
(Lass dich von dem Schwerpunkt auf EBC nicht verunsichern, das ist Top-Of aber kein Must-Have)