Laden...

TCP/IP Daten senden/empfangen

Erstellt von alf468 vor 18 Jahren Letzter Beitrag vor 17 Jahren 59.922 Views
Information von herbivore vor 18 Jahren

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!

A
alf468 Themenstarter:in
196 Beiträge seit 2005
vor 18 Jahren
TCP/IP Daten senden/empfangen

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 ?!

49.485 Beiträge seit 2005
vor 18 Jahren

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

4.506 Beiträge seit 2004
vor 18 Jahren

Hallo alf468!

Wenn Du allgemeine Info's zu TCP/IP haben möchtest, dann schau Dir das an:

MSDN - Networking...

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!”

A
alf468 Themenstarter:in
196 Beiträge seit 2005
vor 18 Jahren

Danke für die Antwort 👍
Ich werde mir das mal anschauen und versuchen in mein Projekt zu übertragen.

A
alf468 Themenstarter:in
196 Beiträge seit 2005
vor 18 Jahren

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?

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo alf468,

nein! 🙂

herbivore

A
alf468 Themenstarter:in
196 Beiträge seit 2005
vor 18 Jahren

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

4.221 Beiträge seit 2005
vor 18 Jahren

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...

A
alf468 Themenstarter:in
196 Beiträge seit 2005
vor 18 Jahren

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

4.221 Beiträge seit 2005
vor 18 Jahren

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...

A
alf468 Themenstarter:in
196 Beiträge seit 2005
vor 18 Jahren

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??

49.485 Beiträge seit 2005
vor 18 Jahren

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

A
alf468 Themenstarter:in
196 Beiträge seit 2005
vor 18 Jahren

Und wie geht sowas??

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo alf468,

einen Rückkanal öffnet man genauso wie den Hinkanal, bloß eben mit vertauschten Rollen.

herbivore

A
alf468 Themenstarter:in
196 Beiträge seit 2005
vor 18 Jahren

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(

402 Beiträge seit 2005
vor 18 Jahren

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.

4.221 Beiträge seit 2005
vor 18 Jahren

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...

A
alf468 Themenstarter:in
196 Beiträge seit 2005
vor 18 Jahren

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?

A
alf468 Themenstarter:in
196 Beiträge seit 2005
vor 18 Jahren

Sieht ganz so aus als wäre das wieder total falsch 🙁

4.221 Beiträge seit 2005
vor 18 Jahren

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...

49.485 Beiträge seit 2005
vor 18 Jahren

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

4.221 Beiträge seit 2005
vor 18 Jahren

@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...

49.485 Beiträge seit 2005
vor 18 Jahren

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

4.221 Beiträge seit 2005
vor 18 Jahren

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...

49.485 Beiträge seit 2005
vor 18 Jahren

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

4.221 Beiträge seit 2005
vor 18 Jahren

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...

A
alf468 Themenstarter:in
196 Beiträge seit 2005
vor 18 Jahren

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 🤔

4.221 Beiträge seit 2005
vor 18 Jahren

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...

A
alf468 Themenstarter:in
196 Beiträge seit 2005
vor 18 Jahren

Wenn ich auf Verbinden klicke kann ich im Fenster nix mehr anklicken.Die Sanduhr ist nur noch da 🙁

4.221 Beiträge seit 2005
vor 18 Jahren

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...

A
alf468 Themenstarter:in
196 Beiträge seit 2005
vor 18 Jahren

Ich danke dir 👍

A
alf468 Themenstarter:in
196 Beiträge seit 2005
vor 18 Jahren

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

49.485 Beiträge seit 2005
vor 18 Jahren

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

K
597 Beiträge seit 2005
vor 17 Jahren
Wenn Client getrennt wurde, und der Server senden möchte

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

57 Beiträge seit 2005
vor 17 Jahren

Sehr guters Beispiel. Danke

4.221 Beiträge seit 2005
vor 17 Jahren

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...

K
597 Beiträge seit 2005
vor 17 Jahren

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

1.815 Beiträge seit 2005
vor 17 Jahren

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 🙁

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo tom-essen,

gute Tutorials nehmen wir immer gerne.

herbivore

1.815 Beiträge seit 2005
vor 17 Jahren

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 🙁

270 Beiträge seit 2005
vor 17 Jahren

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

1.815 Beiträge seit 2005
vor 17 Jahren

Hallo!

Hier noch ein Tutorial zum Thema:
[Tutorial] Client-/Server-Komponente über TCP-Sockets

Nobody is perfect. I'm sad, i'm not nobody 🙁

T
38 Beiträge seit 2006
vor 17 Jahren
funktioniert nicht mit jedem freien Port

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....

4.221 Beiträge seit 2005
vor 17 Jahren

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...