Hi,
ich habe mir hier einen Tcp Server zusammen gebastelt.. bin noch relativ unerfahren in dem Gebiet und wollte fragen, ob (oder besser wie..) es möglich ist, das der Server auch mehrere Clients haben kann. Oder im besten Fall beliebig viele. Über ein Codebeispiel oder sogar eine Verbesserung würde ich mich sehr freuen.
Im Moment empfängt der Server die CPU-Last von einem Client, was dann in dem Label lblReceivedData ausgegeben wird.
namespace Server
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
this.Size = Properties.Settings.Default.Size;
this.Location = Properties.Settings.Default.Location;
this.WindowState = Properties.Settings.Default.WindowState;
}
private void btnStartServer_Click(object sender, EventArgs e)
{
try
{
Thread obj_thread = new Thread(StartServer);
obj_thread.Start();
MessageBox.Show("Server erfolgreich gestartet", "Erfolgreich", MessageBoxButtons.OK, MessageBoxIcon.Information);
btnStartServer.Text = "running...";
btnStartServer.Enabled = false;
}
catch (Exception x)
{
MessageBox.Show(x.Message, "Error", MessageBoxButtons.OK);
}
}
TcpListener obj_server = new TcpListener(IPAddress.Any, 6868);
public void StartServer()
{
obj_server.Start();
while (true)
{
TcpClient tc = obj_server.AcceptTcpClient();
NetworkStream ns = tc.GetStream();
if (ns.ReadByte() == 2)
{
byte[] receive_data = ReadStream(ns);
lblReceivedData.Invoke((MethodInvoker)(() => lblReceivedData.Text = Encoding.UTF8.GetString(receive_data)));
}
}
}
public byte[] ReadStream(NetworkStream ns)
{
byte[] data_buff = null;
int b = 0;
String buff_length = "";
while ((b = ns.ReadByte()) != 4)
{
buff_length += (char)b;
}
int data_length = Convert.ToInt32(buff_length);
data_buff = new byte[data_length];
int byte_read = 0;
int byte_offset = 0;
while (byte_offset < data_length)
{
byte_read = ns.Read(data_buff, byte_offset, data_length + byte_offset);
byte_offset += byte_read;
}
return data_buff;
}
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
Properties.Settings.Default.WindowState = this.WindowState;
Properties.Settings.Default.Size = this.Size;
Properties.Settings.Default.Location = this.Location;
Properties.Settings.Default.Save();
}
}
}
Naja; das ist das was ich im anderen Thread gemeint habe: Du musst Dich jetzt um das gesamte Verbindungsmanagement selbst kümmern, was Dir eben ASP.NET Core abnehmen würde.
Das wird jetzt nen riesen Rattenschwanz....
Das heisst Du brauchst jetzt erstmal eine Art Container oder Liste, wo Du jede einkommende Verbindung quasi als offene Session verwalten musst.
Hinzu kommt eben
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
@Abt
Die Frage ist, ob er dies überhaupt möchte.
Aktuell liest sich das für mich sehr nach einem Lernthema mit dem er sich in Netzwerkprogrammierung einarbeiten will.
Ich halte es daher für den falschen Ansatz ihn davon abbringen zu wollen.
Wenn es zum lernen ist, sollte er hier auch sich damit beschäftigen.
Gerade als Einsteiger sollte man auch TCP/UDP mal programmiert und verstanden haben.
Auf ASP .NET Core würde ich dann im nächsten Schritt eingehen oder wenn es Richtung Web/HTTP geht.
Dann kann man sich ASP .NET Core als fertiges Gesamtpaket anschauen.
Aber aktuell würde ich davon ausgehen, dass dies für den TE nicht das Ziel ist.
@milchmanno
Die TCPListener Klasse bietet hier die AcceptTcpClientAsync Methode.
Diese liefert dir dann einen Task mit dem TcpClient.
Diesen kannst du dann weiterverarbeiten wiederum in einer asynchronen Methode weiterverarbeiten.
Die AccceptTcpClient Methode blockiert bis sich ein Client verbunden hat, weshalb du auch immer nur eine Verbindung annehmen kannst.
Beispiel (Ungetestet):
https://gist.github.com/jamesmanning/2622054
Für Lernzwecke solltest du auch die Doku gründlich lesen.
Den Thread solltest du am besten auch durch einen Task ersetzen, diese lassen sich dann auch besser verarbeiten und beendet.
Ebenfalls wird bei einem eigenen Thread Objekt ein neuer Thread vom OS angefordert, während Tasks sich einen Thread aus dem Threadpool nehmen.
Hier solltest du immer den Threadpool deiner Anwendung verwenden.
T-Virus
Developer, Developer, Developer, Developer....
99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
@Apt
Danke für deine Antwort, du hast bestimmt Recht.
Allerdings muss ich leider eine Windows Form programmieren, da ich ein grafisches UI brauche und mich mit z.B. Web API noch nicht oder nur kurz befasst habe, und meine Kenntnisse einfach noch nicht weit genug sind. Ich werde mir aber auf jeden Fall mal den REST-Client und die ASP.Net Core Version anschauen!
@T-Virus
Danke auch für deine Antwort, die Tipps waren sehr hilfreich. Werde sofort loslegen.
Die Implementierung der Netzwerk-Kommunikation und die Benutzeroberfläche sind aber zwei unterschiedliche Dinge, die auch unabhängig voneinander implementiert werden können und sollten. Siehe dazu [Artikel] Drei-Schichten-Architektur
Weeks of programming can save you hours of planning
Aktuell liest sich das für mich sehr nach einem Lernthema mit dem er sich in Netzwerkprogrammierung einarbeiten will.
Dann les mal die anderen Themen, die wir hier schon zu dieser Software hatten.
Es ist ein Remote Tool für die Serverüberwachung.
Ich halte es daher für den falschen Ansatz ihn davon abbringen zu wollen.
Ich nicht, denn er bindet sich ein riesen Klotz an den Fuß.
Auf ASP .NET Core würde ich dann im nächsten Schritt eingehen oder wenn es Richtung Web/HTTP geht.
ASP.NET Core ist nicht HTTP-only. Bitte die ASP.NET Core Basics zu Middlewares anschauen.
Die AccceptTcpClient Methode blockiert bis sich ein Client verbunden hat, weshalb du auch immer nur eine Verbindung annehmen kannst.
Das stimmt nicht.
AcceptTcpClient ist nur für den initialen Verbindungsaufbau verantwortlich; beschränkt aber nicht die Menge an Verbindungen, die angenommen werden können.
Ja, die asynchrone Methode macht die Sache insgesamt einfacher; ändert die Grundstruktur hier nicht.
Das Blockierne von AcceptTcpClient ist hier im Endeffekt egal, weil es bereits in einen extra Thread ausgelagert wurde.
Es ist hier auch korrekt, dass dies ein extra Thread ist - ein einfacher Task reicht hier nicht (ausser der Task wird mit Task.Run() gestartet, sodass der einzelne Task dann auch in einem eigenen Thread läuft).
Aber das allein ändert die Sache nicht, dass der Code hier nicht für mehrere Clients ausgelegt ist - und zusätzlich eben die starke Vermischung mit der UI.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Hallo,
ich stimme Abt zu. Wenn es um eine Produktivsoftware geht, bitte nicht selber auf TcpListener/TcpClient-Ebene anfangen. Bei allen heutigen Möglichkeiten eignet sich das wirklich nur als Lernthema, oder wenn man was in bestehenden Netzwerksystemen einbinden muss und daher keine anderen Möglichkeiten hat.
Dennoch: Die eigentliche Frage wird in [FAQ] TcpClient: einfaches Beispiel umfangreich behandelt.
Gruß, MarsStein
Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca
Wenn ich richtig (aus anderen Thread) verstanden habe, möchtest du ein Netzwerk-Monitoring aufbauen? Ich würde keine Client/Server Applikation schreiben, sondern auf SNMP/WMI zurückgreifen und die Daten per Dienst live remote abfragen und darstellen, eine Datenbank als temporäre Ablage sollte das Vorhaben gut unterstützen. Die Anwendung kannst du sogar auf mehreren Rechner als Sensor-Server laufen lassen, welche verschiedene Typen von zu überwachenden Client überwacht und Daten in die DB schreibt. Zur Darstellung der Daten kann man einen Webserver dafür verwenden, welche die Daten aus der DB liest und anzeigt
Nur so als Idee 😃
**:::