Laden...

Socket Server Multiclientfähig

Erstellt von guest vor 11 Jahren Letzter Beitrag vor 11 Jahren 2.614 Views
G
guest Themenstarter:in
21 Beiträge seit 2012
vor 11 Jahren
Socket Server Multiclientfähig

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

D
615 Beiträge seit 2009
vor 11 Jahren

Hallo guest

Schau Dir doch mal folgende Beiträge an :
Lauscht der TCPListener permanent nach Verbindungen?

Kleines Chat Program

Beste Grüsse

Diräkt

771 Beiträge seit 2009
vor 11 Jahren

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);
}

G
guest Themenstarter:in
21 Beiträge seit 2012
vor 11 Jahren

@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

6.911 Beiträge seit 2009
vor 11 Jahren

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

G
guest Themenstarter:in
21 Beiträge seit 2012
vor 11 Jahren

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

6.911 Beiträge seit 2009
vor 11 Jahren

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

D
615 Beiträge seit 2009
vor 11 Jahren

Hallo guest

Hier hast du ein perfektes Beispiel ( schau mal die Methode StartListening() an )
Using an Asynchronous Server Socket

Beste Grüsse

Diräkt

J
641 Beiträge seit 2007
vor 11 Jahren

@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

1.346 Beiträge seit 2008
vor 11 Jahren

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

3.170 Beiträge seit 2006
vor 11 Jahren

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

G
guest Themenstarter:in
21 Beiträge seit 2012
vor 11 Jahren

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

W
872 Beiträge seit 2005
vor 11 Jahren

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.