aplikacja klient serwer (asynchronicznie) C#

0

Witam,
w jaki sposób zmodyfikować poniższy kod, aby serwer wysyłał dane do wszystkich klientów:

Kod serwera:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace SnakeServer
{
    class Program
    {
        private static byte[] _buffer = new byte[1024];
        private static List<Socket> _clientSockets = new List<Socket>();
        private static Socket _serverSocket = new Socket
            (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        static void Main(string[] args)
        {
            SetupServer();
            Console.ReadLine();
        }

        private static void SetupServer()
        {
            Console.WriteLine("Setting up server ...");
            _serverSocket.Bind(new IPEndPoint(IPAddress.Any, 100));
            _serverSocket.Listen(10);
            _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);

        }

        private static void AcceptCallback(IAsyncResult AR)
        {
            Socket socket = _serverSocket.EndAccept(AR);
            _clientSockets.Add(socket);
            Console.WriteLine("Client connected");
            socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket);
            _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
        }

        private static void ReceiveCallback(IAsyncResult AR)
        {
            Socket socket = (Socket)AR.AsyncState;
            int received = socket.EndReceive(AR);
            byte[] dataBuf = new byte[received];
            Array.Copy(_buffer, dataBuf, received);

            string text = Encoding.ASCII.GetString(dataBuf);
            Console.WriteLine("Text received: " + text);

            string response = string.Empty;

            if(text.ToLower() == "-1")
            {
                response = "Invalid Request";
            }
            else
            {
                //response = DateTime.Now.ToLongTimeString();
                response = text;
            }
            byte[] data = Encoding.ASCII.GetBytes(response);
            socket.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback(SendCallback), socket);
            socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket);
        }


        private static void SendCallback(IAsyncResult AR)
        {
            Socket socket = (Socket)AR.AsyncState;
            socket.EndSend(AR);
        }
    }
}

Kod klienta:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace SnakeClient
{
    class Program
    {
        private static Socket _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        static void Main(string[] args)
        {
            LoopConnect();
            SendLoop();
            Console.ReadLine();
        }

        private static void SendLoop()
        {
            while (true)
            {
                Console.Write("Enter a request: ");
                string req = Console.ReadLine();
                byte[] buffer = Encoding.ASCII.GetBytes(req);
                _clientSocket.Send(buffer);

                byte[] receivedBuf = new byte[1024];
                int rec = _clientSocket.Receive(receivedBuf);
                byte[] data = new byte[rec];
                Array.Copy(receivedBuf, data, rec);
                Console.WriteLine("received: " + Encoding.ASCII.GetString(data));
            }
        }

        private static void LoopConnect()
        {
            int attempts = 0;

            while (!_clientSocket.Connected)
            {
                try
                {
                    attempts++;
                    _clientSocket.Connect(IPAddress.Loopback, 100);
                }
                catch (SocketException)
                {
                    Console.Clear();
                    Console.WriteLine("Connection attempts: " + attempts.ToString());
                }
            }

            Console.Clear();
            Console.WriteLine("Connected");
        }
    }
}

Teraz dany klient wysyła do serwera żądanie, a serwer przesyła swoją odpowiedź wyłącznie do danego klienta. Próbowałem dodać iterację po wszystkich elementach listy _clientSockets, czyli:

            for (int i = 0; i < _clientSockets.Count; i++)
            {
                socket.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback(SendCallback), _clientSockets[i]);
            }

jednak nie wiem, w którym miejscu i dokładnie w jaki sposób zrealizować to w swoim kodzie - w funkcji SendCallback mamy konkretne gniazdo, dlatego nie będzie to działać jak powinno ...
Jestem całkowicie początkujący jeśli chodzi o programowanie w C#, ogólnie próbuję napisać Snake'a właśnie z wykorzystaniem architektury klient-serwer, aby można była grać wieloosobowo. Ma to działać w ten sposób, że w tle uruchamiamy serwer, a następnie dowolną liczbę graczy, czyli klientów, każdy klient wysyła do serwera współrzędne położenia snake'a oraz położenia owoców, no i serwer powinien odsyłać te informacje do wszystkich pozostałych klientów (graczy). Dzięki temu, będzie można na bieżąco rysować wszystkie węże na planszy każdego z graczy. Ogólnie udało mi się wykorzystać powyższy kod w swojej grze (aplikacja typu WPF), łączenie następuje, póki co wysyłam jedną współrzędną (x-ową), jednak trafia ona z powrotem do danego klienta, który ją wysłał ... poza tym poza wysyłaniem informacji do wszystkich pozostałych klientów trzeba również jakoś zarządzać danymi które są wysyłane, aby mieć kontrolę jakie współrzędne od jakiego klienta dostajemy, które to współrzędne snake'a, a które owoców na planszy itd ....
Czy ktoś jest w stanie dać mi jakieś wskazówki w jaki sposób to zrealizować, jak zmodyfikować ten kod?
Poza tym w jaki sposób można to przerobić używając async/await? Nigdy nie pisałem nic z użyciem tych słów kluczowych ...

0
foreach(socket s in _clientSockets)
{
  data = Encoding.ASCII.GetBytes(twojaWiadomosc);
  s.Send(data);
}

Tak wysyłasz wiadomości do wszystkich połączonych socketów - bo w clientSockets je trzymasz. Polecam zajrzeć na githuba kolesia, która jest twórcą tego kodu.

1 użytkowników online, w tym zalogowanych: 0, gości: 1