Dies ist ein Thread, auf den aus der FAQ verwiesen wird. Bitte keine weitere Diskussion, sondern nur wichtige Ergänzungen und diese bitte knapp und präzise. Vielen Dank!
Ich möchte gerne die Location eines Labels an einem anderen Rechner senden, damit dort das Label genau so positioniert ist.
Das Problem ist ich habe keine Ahnung wie das genau geht X( . Könnt ihr mir ein Beispiel oder ein Hinweis zeigen wo Daten gesendet bzw empfangen werden über TCP/IP ?!
Hallo alf468,
das scheint mir doch eher ein Fall für .NET Remoting (über TCP/IP) - wie in Dateiassoziation gezeigt - zu sein, als für native TCP/IP.
herbivore
Hallo alf468!
Wenn Du allgemeine Info's zu TCP/IP haben möchtest, dann schau Dir das an:
Allerdings muss ich Herbivore recht geben, Remoting ist hier eher ein Stichwort!
Ciao
Norman-Timo
A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”
Danke für die Antwort 👍
Ich werde mir das mal anschauen und versuchen in mein Projekt zu übertragen.
Ich verstehe nicht wie ich das bei mir einbauen kann X( Also was ich vor habe ist ein kleines Brettspiel welches je nach Auswahl alleine oder im Netzwerk gespielt werden kann.
Wenn Multiplayer ausgewählt wurde geht es auf das Spielfeld wo Spieler1 würfelt und die Spielfigur bewegt sich.Spieler2 soll den den gewürfelten Wert sehen zB in einer TextBox oder MessageBox und auch wie sich die Spielfigur bewegt.
Später kommen da noch andere Dinge hinzu die Spieler2 erfahren muss.
Klickt der Spieler auf Würfeln passiert folgendes:
private void button1_Click(object sender, System.EventArgs e)
{
int zuz=zz.Next(1,6);
this.textBox1.Text=zuz.ToString();
for(int j=1;j<=zuz;j++)
{
if(i==8)
{
i=0;
}
this.label9.Location=new Point(Spieler.spieler1x[i],Spieler.spieler1y[i]); // Die Punkte kommen aus einem Array
i++;
this.Refresh();
Thread.Sleep(600);
}
}
Nun müsste beim Multiplayer ja die Location an den Client (Spieler2) gesendet werden.Dazu könnte man eine Methode schreiben welche die Location an alle verbunden IPs schicken bis auf die eigene IP.
Ist für sowas nicht doch native TCP/IP besser?
Hallo alf468,
nein! 🙂
herbivore
Ich finde das mit native TCP/IP einfacher und habe es mal damit Versucht.
1.Problem der Thread
public class ServerThread
{
// Stop-Flag
public bool stop = false;
// Flag für "Thread läuft"
public bool running = false;
// Die Verbindung zum Client
private TcpClient connection = null;
// Speichert die Verbindung zum Client und startet den Thread
public ServerThread ( TcpClient connection )
{
// Speichert die Verbindung zu Client,
// um sie später schließen zu können
this.connection = connection;
// Initialisiert und startet den Thread
new Thread ( new ThreadStart ( Run ) ).Start ();
}
// Der eigentliche Thread
public void Run ()
{
// Setze Flag für "Thread läuft"
this.running = true;
// Hole den Stream für's schreiben
Stream outStream = this.connection.GetStream ();
int buf = 0;
bool loop = true;
while ( loop )
{
try
{
// Hole die aktuelle Zeit als String
int i = Form1.i;
// Sende Zeit nur wenn sie sich von der vorherigen unterscheidet
if ( i!=buf )
{
// Wandele den Zeitstring in ein Byte-Array um
// Es wird noch ein Carriage-Return-Linefeed angefügt
// so daß das Lesen auf Client-Seite einfacher wird
Byte[] sendBytes = Encoding.ASCII.GetBytes ( i + "\r\n" );
// Sende die Bytes zum Client
outStream.Write ( sendBytes, 0, sendBytes.Length );
// Merke die Zeit
buf = i;
}
// Wiederhole die Schleife so lange bis von außen der Stopwunsch kommt
loop = !this.stop;
}
catch ( Exception )
{
// oder bis ein Fehler aufgetreten ist
loop = false;
}
}
}
public void close()
{
// Schließe die Verbindung zum Client
this.connection.Close ();
// Setze das Flag "Thread läuft" zurück
this.running = false;
}
}
Ich bin nach der Anleitung auf http://www.microsoft.com/germany/msdn/library/net/csharp/NetworkingMitCSharp.mspx vorgegangen.
Hier wird die Schleife in der run() ja solange durchlaufen bis die Verbindung getrennt wird.Ich will aber dann Daten senden wenn sich die Spielfigur bewegt und somit die 100% Prozessor auslastung vermeiden.
2.Problem der Client
Der Client stürzt ab was aber auch an der 100% Prozessor auslastung liegen könnte.Den es müsste eigentlic alles stimmen:
private void client()
{
// Verbindung zum Server aufbauen
c = new TcpClient ( "localhost", 4711 );
// Stream zum lesen holen
String buff=null;
StreamReader inStream = new StreamReader ( c.GetStream () );
if(inStream.ReadLine().ToString()!=buff)
{
try
{
MessageBox.Show(inStream.ReadLine().ToString());
// Hole nächsten Zeitstring vom Server
/*int j= int.Parse(inStream.ReadLine ());
this.label9.Location=new Point(Spieler.spieler1x[j],Spieler.spieler1y[j]);
this.Refresh();*/
buff=inStream.ReadLine().ToString();
}
catch ( Exception )
{
// Setze das Schleifen-Flag zurück
// wenn ein Fehler in der Kommunikation aufgetreten ist
this.clientclose();
}
}
}
Eine Verbindung zum Server wird per Buttonklick hergestellt
Ich geb Dir erst mal nur ein paar Stichworte. Da es wichtig ist auch zu VERSTEHEN was im Code abläuft.
GuckstDu in SDK:
-DataAvailable (nur dann liegen Daten an)
-Thread.Sleep (legt den arbeitswütigen Thread schlafen wenn's nix zu tun gibt)
-Thread.Join (wartet beim herunterfahren darauf bis ein anderer Thread ausläuft (sich beendet)) ....
Die Variable loop ist doppelt gemoppelt this.stop reicht doch
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
Thread.Sleep und Thread.Join sind mir bekannt, ich weiß aber nicht wo ich das anwenden soll 🙁
Ich denke du meinst ich soll das Senden der Daten an Client schlafen legen wenn es nix zu gibt.Aber woher soll die Methode wissen wann die Spielfigur sich bewegt ?? 🤔
Mit this.label9.LocationChanged+=new EventHandler(label9_LocationChanged); wird bei Location änderung eine Methode aufgerufen und müsste dann die Daten an den Client gesendet werden
alf486 nimm es mir nicht übel.... aber Du bist relativ weit vom Ziel entfernt.
Ich hab Dir mal ein umfangreiches Sample gebaut, welches auch mit MEHREREN Clients gleichzeitig umgehen kann.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Globalization;
using System.Text;
namespace WindowsApplication9
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Button btnSend;
private System.Windows.Forms.Button btnListen;
private System.Windows.Forms.Button btnConnect;
private System.Windows.Forms.Button btnCloseSender;
private System.Windows.Forms.Button btnStopListen;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btnSend = new System.Windows.Forms.Button();
this.btnListen = new System.Windows.Forms.Button();
this.btnConnect = new System.Windows.Forms.Button();
this.btnCloseSender = new System.Windows.Forms.Button();
this.btnStopListen = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// btnSend
//
this.btnSend.Location = new System.Drawing.Point(200, 80);
this.btnSend.Name = "btnSend";
this.btnSend.Size = new System.Drawing.Size(88, 23);
this.btnSend.TabIndex = 0;
this.btnSend.Text = "Send";
this.btnSend.Click += new System.EventHandler(this.btnSend_Click);
//
// btnListen
//
this.btnListen.Location = new System.Drawing.Point(24, 32);
this.btnListen.Name = "btnListen";
this.btnListen.TabIndex = 1;
this.btnListen.Text = "Listen";
this.btnListen.Click += new System.EventHandler(this.btnListen_Click);
//
// btnConnect
//
this.btnConnect.Location = new System.Drawing.Point(200, 32);
this.btnConnect.Name = "btnConnect";
this.btnConnect.Size = new System.Drawing.Size(88, 23);
this.btnConnect.TabIndex = 2;
this.btnConnect.Text = "Connect";
this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click);
//
// btnCloseSender
//
this.btnCloseSender.Location = new System.Drawing.Point(200, 128);
this.btnCloseSender.Name = "btnCloseSender";
this.btnCloseSender.Size = new System.Drawing.Size(88, 23);
this.btnCloseSender.TabIndex = 3;
this.btnCloseSender.Text = "Close Sender";
this.btnCloseSender.Click += new System.EventHandler(this.btnCloseSender_Click);
//
// btnStopListen
//
this.btnStopListen.Location = new System.Drawing.Point(24, 80);
this.btnStopListen.Name = "btnStopListen";
this.btnStopListen.TabIndex = 4;
this.btnStopListen.Text = "Stop Listen";
this.btnStopListen.Click += new System.EventHandler(this.btnStopListen_Click);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(328, 301);
this.Controls.Add(this.btnStopListen);
this.Controls.Add(this.btnCloseSender);
this.Controls.Add(this.btnConnect);
this.Controls.Add(this.btnListen);
this.Controls.Add(this.btnSend);
this.Name = "Form1";
this.Text = "t";
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private Hashtable _HtClients=new Hashtable();
private TcpClient _TcpClientSender;
private NetworkStream _SendStream;
private Thread _ListenerThread;
private bool _ListenerStop=false;
private TcpListener _TcpListener;
private void Listen()
{
this._TcpListener=new TcpListener(IPAddress.Parse("0.0.0.0"),6667);
this._TcpListener.Start();
do
{
bool iHadWork=false;
//prüfe ob Verbindungsanforderungen anstehen
if (this._TcpListener.Pending())
{
TcpClient client=this._TcpListener.AcceptTcpClient();
this._HtClients.Add(client,client.GetStream());
iHadWork=true;
}
else
{
//prüfe ob für offene Clients Daten da sind
foreach (TcpClient client in this._HtClients.Keys)
{
NetworkStream ns=this._HtClients[client]as NetworkStream;
if (ns.DataAvailable)
{
//oho wir haben Daten erhalten
byte[] bytes=new byte[client.ReceiveBufferSize];
int intBytesRead=ns.Read(bytes,0,client.ReceiveBufferSize);
string sReceived=Encoding.Default.GetString(bytes,0,intBytesRead);
this.Text=sReceived;
iHadWork=true;
}
}
}
if (!iHadWork)
{
Thread.Sleep(100);
}
}while (!this._ListenerStop);
foreach (TcpClient client in this._HtClients.Keys)
{
NetworkStream ns=this._HtClients[client]as NetworkStream;
ns.Close();
client.Close();
}
}
private void btnListen_Click(object sender, System.EventArgs e)
{
this._ListenerThread=new Thread(new ThreadStart(this.Listen));
this._ListenerThread.Start();
}
private void btnStopListen_Click(object sender, System.EventArgs e)
{
this._ListenerStop=true;
this._ListenerThread.Join();
}
private void btnConnect_Click(object sender, System.EventArgs e)
{
this._TcpClientSender=new TcpClient();
this._TcpClientSender.Connect(IPAddress.Parse("192.168.2.2"),6667);
this._SendStream=this._TcpClientSender.GetStream();
}
private void btnSend_Click(object sender, System.EventArgs e)
{
string sToSend=DateTime.Now.ToLongTimeString();
byte[] bytesToSend=Encoding.Default.GetBytes(sToSend);
this._SendStream.Write(bytesToSend,0,bytesToSend.Length);
}
private void btnCloseSender_Click(object sender, System.EventArgs e)
{
this._SendStream.Close();
this._TcpClientSender.Close();
}
}
}
Und siehst Du jetzt wo DataAvailable und Thread.Join sind ??
Gruss
Programmierhans
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
Erst einmal vielen vielen Dank für die Arbeit die du dir gemach hast 👍
Habe aber noch eine Frage wie kann der Server an Client Daten senden??
Hallo alf468,
wenn man keinen Rückkanal öffnet, bei dem der Server zum Client und der Client zum Server wird, nur indem der Server auf eine Anfrage des Clients antwortet.
herbivore
Und wie geht sowas??
Hallo alf468,
einen Rückkanal öffnet man genauso wie den Hinkanal, bloß eben mit vertauschten Rollen.
herbivore
Ich habe mal versucht das irgendwie zu machen.
//prüfe ob für offene Clients Daten da sind
foreach (TcpClient client in this._HtClients.Keys)
{
NetworkStream ns=this._HtClients[client]as NetworkStream;
if (ns.DataAvailable)
{
//oho wir haben Daten erhalten
Stream outStream=client.GetStream();
byte[] bytes=new byte[client.ReceiveBufferSize];
int intBytesRead=ns.Read(bytes,0,client.ReceiveBufferSize);
String j=Encoding.Default.GetString(bytes,0,intBytesRead);
outStream.Write(bytes,0,intBytesRead); //Daten an Client senden?
//MessageBox.Show(j);
this.label9.Location=new Point(Spieler.spieler1x[int.Parse(j)],Spieler.spieler1y[int.Parse(j)]);
this.Refresh();
iHadWork=true;
}
}
this._TcpClientSender=new TcpClient();
this._TcpClientSender.Connect(IPAddress.Parse("127.0.0.1"),6667);
this._SendStream=this._TcpClientSender.GetStream();
_HtClients2.Add(this._TcpClientSender,this._TcpClientSender.GetStream());
foreach (TcpClient client in _HtClients2.Keys)
{MessageBox.Show("kdöl");
NetworkStream ns=this._HtClients2[client]as NetworkStream;
if (ns.DataAvailable)
{
//oho wir haben Daten erhalten
Stream outStream=client.GetStream();
byte[] bytes=new byte[client.ReceiveBufferSize];
int intBytesRead=ns.Read(bytes,0,client.ReceiveBufferSize);
String j=Encoding.Default.GetString(bytes,0,intBytesRead);
outStream.Write(bytes,0,intBytesRead);
//MessageBox.Show(j);
this.label9.Location=new Point(Spieler.spieler1x[int.Parse(j)],Spieler.spieler1y[int.Parse(j)]);
this.Refresh();
//iHadWork=true;
}
}
Ich hoffe ihr denkt jetzt nicht was macht der da für ein Quatsch aber ich verstehe nicht wie ich das umsetzten soll X(
Oder nimm einfach die bekannte Indy-Library, wenn Du es Dir nicht so schwer machen wills: Indy Library .NET
Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning.
Im Prinzip musst Du ja die Positionen eh an alle Clients senden....
Also kopierst Du dir den Code zusammen
foreach client ......
den Stream des Clients verwenden
Daten senden
Den Code hast Du ja schon.... musst nur für die Rückantworten den Code neu zusammensetzen (ohne den anderen Code zu zerstören)
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
Damit der Server an die Clients Daten sendet müsste ich den NetworkStream vom jeweiligen Client nehmen und damit dann die Daten senden.
foreach (TcpClient client in this._HtClients.Keys)
{
NetworkStream ns=this._HtClients[client]as NetworkStream;
if (ns.DataAvailable)
{
//oho wir haben Daten erhalten
byte[] bytes=new byte[client.ReceiveBufferSize];
int intBytesRead=ns.Read(bytes,0,client.ReceiveBufferSize);
String j=Encoding.Default.GetString(bytes,0,intBytesRead);
ns.Write(bytes,0,client.ReceiveBufferSize); //Senden der Empfangen Daten an Client
this.label9.Location=new Point(Spieler.spieler1x[int.Parse(j)],Spieler.spieler1y[int.Parse(j)]);
this.Refresh();
iHadWork=true;
}
}
Wobei nach diesem Code jetzt nur an den Client gesendet wird welcher gerade Daten schickt aber zum testen reicht es ja erst einmal.
Damit der Client Daten empfängt müsste ich ein NetworkStream für den Client erstellen.
Ich habe das jetzt mal direkt beim Verbinden zum Server gemacht
this._TcpClientSender=new TcpClient();
this._TcpClientSender.Connect(IPAddress.Parse("127.0.0.1"),6667);
this._SendStream=this._TcpClientSender.GetStream();
NetworkStream nsc=this._SendStream as NetworkStream;
if(nsc.DataAvailable)
{
byte[] bytes=new byte[this._TcpClientSender.ReceiveBufferSize];
int intBytesRead=nsc.Read(bytes,0,this._TcpClientSender.ReceiveBufferSize);
String j=Encoding.Default.GetString(bytes,0,intBytesRead);
MessageBox.Show(j);
}
Ist das jetzt Ansatzweise richtig?
Sieht ganz so aus als wäre das wieder total falsch 🙁
Im ersten Codeblock sendest Du ein leeres ByteArray ! GuckstDu Encoding.GetBytes an....
und im zweiten Codeblock läuft er nur einmal direkt durch (weil DataAvailable noch auf false ist).... da muss ne Schlaufe hin (und das ThreadSleep nicht vergessen)
Ich lass Dich nicht ganz hängen, aber alles will ich ja auch nicht für Dich coden... sonst lernst Du ja nichts....
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
Hallo alf468,
dann versuche ich nochmal ganz zaghaft auf mein Remoting-Beispiel hinzuweisen. Dabei muss man sich gar nicht mit dem Netzwerk auseinandersetzen, sondern spricht in dem einem Prozess nur ganz normal ein Objekt (im Beispiel ArgsReceviver) an, dass sich in dem anderen Prozess befindet und dort die gewünschte Aktion ausführen kann.
herbivore
@hebivore
Er braucht doch aber eine Bidirektionale Triggerung.... das würde bei Remoting zusätzlich Channels bedeuten.
Wenn nun das Spiel wenn es dann mal fertig wird über das Internet gespielt werden soll läuft er dann mit den Channels nicht voll gegen die Wand (Firewalls) ?
Gruss
Programmierhans
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
Hallo Programmierhans,
Er braucht doch aber eine Bidirektionale Triggerung.... das würde bei Remoting zusätzlich Channels bedeuten.
Finde ich nicht so schlimm. 🙂
Wenn nun das Spiel wenn es dann mal fertig wird über das Internet gespielt werden soll läuft er dann mit den Channels nicht voll gegen die Wand (Firewalls) ?
Doch nicht mehr oder weniger, wenn er direkt mit TCP/IP oder gar Sockets arbeitet.
herbivore
Original von herbivore
Doch nicht mehr oder weniger, wenn er direkt mit TCP/IP oder gar Sockets arbeitet.
herbivore
Doch, denn bei TcpClient oder Sockets definiert er alle Ports.... oder kann man für Channels auch Ports definieren...?
Wobei meine Meinung zu Channels kennst Du ja.... (ich werde mich hüten nochmal was mit Channels zu bauen... denn in einem instabilen Netz bist Du tot mit Channels)... bei Sockets hast Du's wenigstens selber im Griff
Gruss
Programmierhans
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
Hallo Programmierhans,
oder kann man für Channels auch Ports definieren...?
Wenn du damit meinst, dass man den Port festlegen kann, dann ja:
ChannelServices.RegisterChannel (new TcpChannel (4711));
herbivore
ok herbivore
Der mit dem Port geht an Dich.... was aber nichts an meiner Meinung ändert.
Gruss
Programmierhans
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
Original von Programmierhans
Im ersten Codeblock sendest Du ein leeres ByteArray ! GuckstDu Encoding.GetBytes an....und im zweiten Codeblock läuft er nur einmal direkt durch (weil DataAvailable noch auf false ist).... da muss ne Schlaufe hin (und das ThreadSleep nicht vergessen)
Ich lass Dich nicht ganz hängen, aber alles will ich ja auch nicht für Dich coden... sonst lernst Du ja nichts....
Sollst du ja auch nicht 😉
Also das erste habe ich jetzt geändert
byte[] bytesToSend=Encoding.Default.GetBytes("test");
ns.Write(bytesToSend,0,bytesToSend.Length);
Den zweiten Block auch
while(!this._ClientStop)
{
if(nsc.DataAvailable)
{
byte[] bytes=new byte[this._TcpClientSender.ReceiveBufferSize];
int intBytesRead=nsc.Read(bytes,0,this._TcpClientSender.ReceiveBufferSize);
String j=Encoding.Default.GetString(bytes,0,intBytesRead);
//work=true;
}
else
{
Thread.Sleep(100);
}
}
Der Client stürzt nun aber beim Verbinden was aber sicher daran liegt das die Schleife erst "zu Ende" läuft 🤔
Original von alf468
Der Client stürzt nun aber beim Verbinden was aber sicher daran liegt das die Schleife erst "zu Ende" läuft 🤔
Fehlermeldung ?
Stack ?
Ort wo er steht ?
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
Wenn ich auf Verbinden klicke kann ich im Fenster nix mehr anklicken.Die Sanduhr ist nur noch da 🙁
das kommt von deinem endlosloop...
mach da mal ein Application.DoEvents() rein
Edit:
Im Uebrigen ist dies nicht ein Absturz sondern ein "Hängen"
Application.DoEvents gehört nie in ein produktives Programm rein... wurde hier von mir nur vorgeschlagen um in einem einfachen Szenario zu zeigen was abgeht.
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
Ich danke dir 👍
Je nachdem ob der User Singleplayer oder Multiplayer auswählt soll eine andere Klasse geladen werden.Die Klassen habe ich jeweils in eine dll Datei geschrieben (ein komplettes Fenster) .Nun will ich aber dass sich kein neues Fenster öffnet sondern dass das alte Fenster mit dem Menü überschrieben wird. Also das gleiche als würde eine neue InitializeComponent() geladen werden.
Ich will hat diesen Übergangseffekt vermeiden wo sich ein Fenster schließt und ein neues öffnet
Hallo alf468,
das ist ein komplett anderes Thema und gehört m.E. in einen anderen Thread (und in ein anderes Forum, nämlich Windows Forms).
herbivore
Hallo Zusammen,
Wenn sich ein Client auf dem Server verbindet, wird im Beispielcode
vom Programmierhans die connection in eine Hashtable gespeichert.
Somit kann der Server eine Nachricht zum Client senden.
Es kann vorkommen das der Client sich unsachgemäß beendet und der
Server nichts davon mitbekommt.
Wie behandelt man diesen Zustand richtig?
Gruß Kostas
Sehr guters Beispiel. Danke
Beim 2ten Sendevorgang an einen toten Client gibt es eine Exception.
Dann wird der tote Client aus der Hashtable entfernt.
Bei sehr wichtigen Daten (wo absolut nichts verloren gehen darf) empfehle ich die Verwendung eines Handshakes... (der Client schickt etwas zurück um dem Sender mitzuteilen dass er die Message erhalten und gegebenenfalls verarbeitet hat.
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
Danke Programierhans,
ich werde einfach die exception auswerten nach dem Senden.
Ich habe aktuell ein weiteres Problem. Ich kann die Methode
private void Listen() nicht debugen. Wenn ich ein Haltepunkt
auf
this._TcpListener = new TcpListener(IPAddress.Parse("0.0.0.0"), 4711);
setze, springt er an dieser stelle hin, kann aber nicht per Einzelschritt
weitermachen. Es springt einfach raus und macht weiter. Zumindest habe ich
das Gefühl das er weiter macht.
Kann es sein das es etwas mit die Threads zu tun hat?
Gruß Kostas
Hallo!
Bin grade dabei, für das Client-/Server-Problem eine Komponente zu schreiben, welche den Programmierer von der eigentlichen Implementierung erlöst und entsprechende Mechanismen, etc. zur Verfügung stellt.
Falls Interesse daran besteht, mach ich da gern ein Tutorial draus, und werd' auch selbstverständlich den Code inkl. Beispiel hier posten.
Nobody is perfect. I'm sad, i'm not nobody 🙁
Hallo tom-essen,
gute Tutorials nehmen wir immer gerne.
herbivore
OK, hab's mir schonmal notiert.
Wird aber noch ca. 2 Wochen dauern, bis ich anfangen kann, da ich z.Zt. noch in einem grossen Projekt an der Uni arbeite, nur damit alle Interessierten schonmal bescheid wissen 😉
Nobody is perfect. I'm sad, i'm not nobody 🙁
Hallo zusammen,
hätte da noch ne kurze Frage zu dem hier beschriebenen Thread.
Und zwar wie/ist es möglich das der TCP-Listner die IP der bei Ihm connecteten
Clients sammeln kann?!
Mir ist klar das die Clients dem Server(Listener) dies Daten auch per Datenstrom schicken könnten jedoch währe das ja eine Übertragung die unnötig ist da er intern wissen muss wie die IP ist (im Hastablet ist der Client ja gespeichert).
Biete das Objekt Client eine Möglichkeit die Ip des Client zu ermitteln?
mfg der Hulk
Hallo!
Hier noch ein Tutorial zum Thema:
[Tutorial] Client-/Server-Komponente über TCP-Sockets
Nobody is perfect. I'm sad, i'm not nobody 🙁
hallo,
ich habe ein merkwürdiges phänomen:
wenn ich das Sample mit ip 127.0.0.1 laufen lasse und Port 10000 nehme, dann klappt das Sample nicht.
Nehme ich den Port 6667, dann läuft das Sample, obwohl beide Ports unbenutzt sind.
Woran kann das liegen?
There are 10 diffent types of people in this world: Those who understand binary and those who don't....
Port 10000 ist doch reserviert für ... guckst Du hier: http://www.ndmp.org/
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...