Асинхронный клиент-серверное приложение с обработкой данных

Мне нужно при подключение клиента с серверу вывести данные от клиента (IP, UserName) в ListView это у меня как бы получается, но суть в другом, данные которые поступают от клиента на сервер нужно обработать отдельно (текстовое сообщение которое отправляется от клиента на сервер)

Listview (отображает айпи и имя клиента) после из контекстного меню выбираю открыть другую форму и в другой форме есть кнопка и текстбокс, мне нужно вывести данные в другой форме от выбранного клиента те данные которые передаются от Console.ReadLine (client)

Вот код клиента:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace Client
{
    public static class SocketClient
    {
        private const int Port = 11000;
        private const string ServerIp = "127.0.0.1";

        public static async Task Start()
        {
            while (true)
            {
                using (var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
                {
                    try
                    {
                        Console.WriteLine($"Попытка подключения к серверу: {ServerIp}:{Port}");
                        await client.ConnectAsync(ServerIp, Port);
                        Console.WriteLine($"Подключено к серверу: {ServerIp}:{Port}");

                        string userName = Environment.UserName; // Получаем имя пользователя
                        string ip = GetLocalIpAddress(); // Получаем локальный IP-адрес

                        // Формируем данные о подключившемся пользователе
                        string userData = $"{ip},{userName}";
                        byte[] userDataBytes = Encoding.UTF8.GetBytes(userData); // Кодируем данные в байты

                        // Отправляем данные о пользователе серверу
                        await client.SendAsync(new ArraySegment<byte>(userDataBytes), SocketFlags.None);

                        var receiveTask = Task.Run(() => ReceiveMessages(client));
                        await SendMessages(client);
                    }
                    catch (SocketException ex)
                    {
                        Console.WriteLine($"Ошибка подключения к серверу: {ex.Message}. Повторная попытка подключения через 3 секунды.");
                        await Task.Delay(3000);
                    }
                }
            }
        }

        private static async Task SendMessages(Socket client)
        {
            while (true)
            {
                Console.Write("Введите сообщение для сервера: ");
                string message = Console.ReadLine();
                byte[] data = Encoding.UTF8.GetBytes(message);
                await client.SendAsync(new ArraySegment<byte>(data), SocketFlags.None);
            }
        }

        private static async Task ReceiveMessages(Socket client)
        {
            byte[] buffer = new byte[1024];
            while (true)
            {
                int bytesRead = await client.ReceiveAsync(new ArraySegment<byte>(buffer), SocketFlags.None);
                string data = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                Console.WriteLine($"Получено от сервера: {data} | размер: {bytesRead} КБ");
            }
        }

        private static string GetLocalIpAddress()
        {
            string localIp = string.Empty;
            IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());

            foreach (IPAddress ip in host.AddressList)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    localIp = ip.ToString();
                    break;
                }
            }

            return localIp;
        }
    }
}

Вот код сервера:

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Server
{
    public partial class PanelServ : Form
    {
        // В PanelServ форме создайте приватное поле для хранения данных клиентов
        public List<ClientData> clientDataList = new();
        public int selectedClientIndex; // Индекс выбранного клиента
        private Socket listener;
        private Task listeningTask;
        private int connectedClientsCount = 0;

        public PanelServ()
        {
            InitializeComponent();
            contextMenuStrip1.Opening += new System.ComponentModel.CancelEventHandler(contextMenuStrip1_Opening); // событие подписки на проверку контекстного меню
        }

        private void openLogsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (listView1.SelectedItems.Count > 0)
            {
                // Получение выбранного элемента ListView
                ListViewItem selectedItem = listView1.SelectedItems[0];

                // Сохранение индекса выбранного клиента
                selectedClientIndex = selectedItem.Index;

                // Открытие формы LogClientFrm
                LogClientFrm log = new LogClientFrm();
                log.Show();
            }
        }

        private void contextMenuStrip1_Opening(object sender, System.ComponentModel.CancelEventArgs e)
        {
            e.Cancel = listView1.Items.Count == 0; // Проверка элементов в ListView и если есть показываем контекстное меню
        }

        private async void ListenClientBtn_Click(object sender, EventArgs e)
        {
            listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            listener.Bind(new IPEndPoint(IPAddress.Any, Convert.ToInt32(PortText.Text)));
            listener.Listen(100);
            InfoListen.Text = $"Listen Port Clients: {Convert.ToInt32(PortText.Text)}";
            listeningTask = StartListening();
            await listeningTask;
        }

        private async Task StartListening()
        {
            while (true)
            {
                Socket client = await listener.AcceptAsync();
                InfoClient.Text = "Count clients: 0";

                string ip = client.RemoteEndPoint.ToString();
                string user = ""; // Здесь вы можете установить нужное значение

                ListViewItem item = new(new[] { ip, user });
                listView1.Items.Add(item);

                connectedClientsCount++;

                // Создаем экземпляр класса ClientData и заполняем его данными
                ClientData clientData = new ClientData
                {
                    IP = ip,
                    User = user
                };
                // Добавляем данные клиента в список
                clientDataList.Add(clientData);

                InfoClient.BeginInvoke(new Action(() =>
                {
                    InfoClient.Text = $"Count clients: {connectedClientsCount}";
                }));

                await ReceiveDataFromClient(client, item, clientData);
            }
        }

        private async Task ReceiveDataFromClient(Socket client, ListViewItem item, ClientData clientData)
        {
            try
            {
                byte[] buffer = new byte[1024];
                while (true)
                {
                    int bytesRead = await client.ReceiveAsync(new ArraySegment<byte>(buffer), SocketFlags.None);
                    string data = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                    string[] userData = data.Split(','); // Разделяем полученные данные на IP-адрес и имя пользователя
                    if (userData.Length >= 3) 
                    {
                        string ip = userData[0];
                        string user = userData[1];
                        string message = userData[2];

                        listView1.BeginInvoke(new Action(() =>
                        {
                            item.SubItems[0].Text = ip;
                            item.SubItems[1].Text = user;
                        }));
                        clientData.Message = message;
                    }
                }
            }
            catch (Exception)
            {
               // Console.WriteLine($"Ошибка при обработке клиента: {ex.Message}");
            }
            finally
            {
                client.Shutdown(SocketShutdown.Both);
                client.Close();
                listView1.BeginInvoke(new Action(() =>
                {
                    listView1.Items.Remove(item);
                }));

                connectedClientsCount--; // Уменьшаем счетчик подключенных клиентов
                                         // Обновляем счетчик в label
                InfoClient.BeginInvoke(new Action(() =>
                {
                    InfoClient.Text = $"Подключёно клиентов: {connectedClientsCount}";
                }));
            }
        }
    }

    public class ClientData
    {
        public string IP { get; set; }
        public string User { get; set; }
        public string Message { get; set; } // тут нужны данные которые поступают от клиента (Console.ReadLine) и в дальнейшем можно будет вывести данные в текстбокс.
    }
}

Код сервера (отдельной формы):

using System;
using System.Windows.Forms;

namespace Server
{
    public partial class LogClientFrm : Form
    {
        private PanelServ parentForm; // Ссылка на родительскую форму (PanelServ)

        public LogClientFrm()
        {
            InitializeComponent();
            // Получение ссылки на родительскую форму
            parentForm = (PanelServ)Owner;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // Получение данных от выбранного клиента
            ClientData selectedClientData = parentForm.clientDataList[parentForm.selectedClientIndex];

            // Отображение данных в текстовом поле
            textBox1.Text = selectedClientData.Message;
        }
    }
}

P.S: Нужно именно по Socket (не TCP)
Какие вообще идеи предложите по данной реализации.
Желательно с комментариями по коду, чтобы было понятно что как и где.
Проект на .NetFramework 4.7.2 введите сюда описание изображения


Ответы (0 шт):