Hallo, ich bin im Networking noch sehr neu und möchte euch fragen wie ich einen Server Multiclientfähig machen kann?
Erstmal meinen Server:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.Threading;
using Client;
namespace Server
{
class Program1
{
static void Main(string[] args)
{
DateTime d1 = DateTime.UtcNow;
Console.ForegroundColor = ConsoleColor.DarkRed;
Socket socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken ct = cts.Token;
try
{
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sock.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"),3123));
sock.Listen(1000);
Console.WriteLine("[{0}] >> Server wartet auf Verbindungswunsch", d1.TimeOfDay);
Task.Factory.StartNew(receive =>
{
try
{
Socket cS = sock.Accept();
Console.WriteLine("[{0}] >> Client Connected", d1.TimeOfDay);
while (true)
{
byte[] buffer = new byte[256];
int bytes = cS.Receive(buffer);
Console.WriteLine("[{1}] >> {0}", ASCIIEncoding.ASCII.GetString(buffer, 0, bytes), d1.TimeOfDay);
}
}
catch
{
Console.WriteLine("Client disconncted");
}
}, ct);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message,"Exception");
}
Console.Read();
}
}
}
Wenn ich mich jetzt mit einem Client verbinde und ich mit dem Server "chatte" funktioniert alles super.
Doch, wenn ich mich mit einem zweiten Client verbinde funktioniert es nichtmehr, bzw. beim Server kommen die Nachrichten nicht an, und es wird beim Server auch kein weiteres "Client connected" ausgegeben.
Wie muss ich das machen?
Ich hab schon gegooglet, youtube videos gesucht, bei msdn geschaut. Doch ich finde nichts konkretes dazu.
extinct
Hallo guest
Schau Dir doch mal folgende Beiträge an :
Lauscht der TCPListener permanent nach Verbindungen?
Beste Grüsse
Diräkt
Hi,
du mußt nach Socket.Accept einen neuen Thread (bzw. Task) starten und dann im Hauptthread wieder diese Methode aufrufen:
while(true)
{
Socket socket = sock.Accept();
Task.Factory.StartNew(s =>
{
while (true)
{
byte[] buffer = new byte[256];
int bytes = s.Receive(buffer);
Console.WriteLine("[{1}] >> {0}", ASCIIEncoding.ASCII.GetString(buffer, 0, bytes), d1.TimeOfDay);
}
},
socket);
}
@Diräkt: Danke fuer deine Antwort, aber ich moechte TcpListener eigentlich vermeiden, da die Klasse etwas alt ist, Socket ist da bischen moderner.
@ Cat:
Also Soll das dann so aussehen?:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.Threading;
using Client;
namespace Server
{
class Program1
{
static void Main(string[] args)
{
DateTime d1 = DateTime.UtcNow;
Console.ForegroundColor = ConsoleColor.DarkRed;
Socket socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken ct = cts.Token;
try
{
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sock.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"),3123));
sock.Listen(1000);
Console.WriteLine("[{0}] >> Server wartet auf Verbindungswunsch", d1.TimeOfDay);
Task.Factory.StartNew(receive =>
{
try
{
while (true)
{
Socket cS = sock.Accept();
Console.WriteLine("[{0}] >> Client Connected", d1.TimeOfDay);
Task.Factory.StartNew(s=>
{
while(true){
byte[] buffer = new byte[256];
int bytes = cS.Receive(buffer);
Console.WriteLine("[{1}] >> {0}", ASCIIEncoding.ASCII.GetString(buffer, 0, bytes), d1.TimeOfDay);
}
},cS);
}
}
catch
{
Console.WriteLine("Client disconncted");
}
}, ct);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message,"Exception");
}
Console.Read();
}
}
}
extinct
Hallo Cat und guest,
wenn hier Tasks verwendet werden, so sollte als TaskCreationOption LongRunning
verwendet werden, da somit ein eigener Thread erstellt wird und keiner aus dem ThreadPool verwendet wird. ThreadPool-Thread sollten eher für kurze Aufgaben (ein paar Zehntelsekunden) verwendet werden und hier ist Lebensdauer des Tasks i.d.R. wohl deutlich höher.
mfG Gü
Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.
"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"
Danke fuer den Tipp gfoidl.
Aber wird dann auch einen Hintergrundtask erzeugt? Oder beeinflusst die Option longrunning das?
Weil wenn man ja einen Task erzeugt, wird dieser ja zum Hintergrundtask, automatisch
Und wiederum zur anderen Frage, ist der Code den ich gepostet habe korrekt? Augenommen, dass die option longrunning nicht aktiviert ist.
extinct
Hallo guest,
mit LongRunning ist es auch ein Hintergrund-Thread. Bei Tasks gibt es die Unterscheidung Vorder-/Hintergrund nicht, nur bei Threads.
Obs korrekt ist, weiß ich nicht, da ich mich mit Sockets nicht so gut auskenne. Da weiß Cat od. Diräkt sicher mehr zu berichten.
mfG Gü
Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.
"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"
Hallo guest
Hier hast du ein perfektes Beispiel ( schau mal die Methode StartListening() an )
Using an Asynchronous Server Socket
Beste Grüsse
Diräkt
@Diräkt: Danke fuer deine Antwort, aber ich moechte TcpListener eigentlich vermeiden, da die Klasse etwas alt ist, Socket ist da bischen moderner.
Wo steht das? Ichdenke Socket Ist da einfach ein Level weniger Abstrahiert! Aber TCPListener veraltet??
cSharp Projekte : https://github.com/jogibear9988
Generell ist es aber nicht wirklich gut Threads dafür zu verschwenden auf eine Netzwerkanfrage zu warten. Da ist das benutzen von asynchronen Methoden deutlich sparsamer. Wenn man C# 5 zur Verfügung hat sieht die asynchrone Variante ohne Threads fast genau so aus
Hallo,
aber ich moechte TcpListener eigentlich vermeiden, da die Klasse etwas alt ist, Socket ist da bischen moderner.
Das stimmt so nicht. Die Klassen TcpListener
/TcpClient
verwenden intern auch Socket, nur dass ein Socket eben noch viel mehr kann als Tcp => die beiden Klassen sind genau dafür da, für Tcp-Verbindungen den Zugriff auf die Sockets zu vereinfachen. Solange Du bei Tcp bleiben willst, gibt es überhaupt keinen Grund, direkt mit den Sockets zu arbeiten.
Gruß, MarsStein
Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca
Hier hast du ein perfektes Beispiel ( schau mal die Methode StartListening() an )
Using an Asynchronous Server Socket
Also ich sehe und kenne keine Methode die StartListening heißt. Sofern du die Klasse Socket meinst
extinct
Socket ist ein C#-Wrapper um die native Winsocket 2 Klasse . Diese Socket Klasse unterstuetzt mit einem API verschiedene Transport-Protokolle (z.B. TCP und UDP). Weiterhin kann ein Socket sowohl fuer Server als auch Client Anwendungen genutzt werden.
Ein TCPListener ist eine spezielle C# Komponente fuer TCP Server basierend auf Sockets. Wie Du selber gemerkt hast, ist das TCPListener Protokoll spezieller als das von Socket auf einen TCP Server abgestimmt. Start waere z.B. ein Bind und dann ein Listen mit bestimmten Flags.
Edit:
Falls es Dich interessiert, kannst Du Dir auch mit dem ILSpy die Implementierung von TCPListener anschauen/angepasst verwenden.
MSDN sagt so schoen:
If you are writing a relatively simple application and do not require maximum performance, consider using TcpClient, TcpListener, and UdpClient. These classes provide a simpler and more user-friendly interface to Socket communications.