• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Aplikacja klient serwer nie działa prawidłowo

VPS Starter Arubacloud
0 głosów
193 wizyt
pytanie zadane 26 marca 2017 w C# przez timrh Mądrala (6,030 p.)

Witam mam problem, otóż napisałem aplikację kliencką:

 

using System.Net.Sockets;
using System.Net;
using System.IO;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace Client
{
    class Program
    {
        private static TcpClient    client = new TcpClient();
        private static StreamReader reader;
        private static StreamWriter writer;

        private static bool         refresh;
        private static List<string> messages = new List<string>();

        public static void Main()
        {
            Console.Title = "Client";
            
            do //try to connect
            {
                Console.WriteLine("Connecting to server...");

                try
                {
                    client.Connect(IPAddress.Parse("127.0.0.1"), 8080);
                }
                catch (SocketException) { }

                Thread.Sleep(10);
            } while (!client.Connected);
            
            // \/ CONNECTED \/

            Console.WriteLine("Connected.");

            reader = new StreamReader(client.GetStream());
            writer = new StreamWriter(client.GetStream());

            var sendTask       = Task.Run(() => SendMessage());          //task for sending messages
            var recieveTask    = Task.Run(() => RecieveMessage());       //task for recieving messages
            var updateConvTask = Task.Run(() => UpdateConversation());   //task for update console window

            Task.WaitAll(sendTask, recieveTask); //wait for end of all tasks
        }

        private static void SendMessage()
        {
            string msgToSend = string.Empty;
            do
            {
                Console.WriteLine("Enter a message to send to the server");
                msgToSend = Console.ReadLine();
                writer.WriteLine(msgToSend);
                writer.Flush();
            } while (!msgToSend.Equals("Exit"));
            EndConnection();
        }

        private static void RecieveMessage()
        {
            try
            {
                while (client.Connected)
                {
                    //Console.Clear();
                    string msg = reader.ReadLine();

                    if(msg != string.Empty)
                    {
                        if (msg == "%C") //special message from server, clear messages if recieve it
                        {
                            messages.Clear();
                        }
                        else
                        {
                            messages.Add(msg);
                            refresh = true; //refresh console window
                        }
                    }
                    //Console.Clear();
                    //Console.WriteLine(msgFromServer);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }

        private static void UpdateConversation()
        {
            //string conversationTmp = string.Empty;

            try
            {
                while (true)
                {
                    if (refresh) //only if refresh
                    {
                        refresh = false;
                        Console.Clear();
                        messages.ForEach(msg => Console.WriteLine(msg)); //write all messages
                        Console.WriteLine();
                    }
                }
            }
            catch (Exception) { }
        }

        private static void EndConnection()
        {
            reader.Close();
            writer.Close();
            client.Close();
        }

    }
}

Oraz serwerową:

using System;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Server
{
    class Program
    {
        private static List<Client> clients = new List<Client>();
        private static TcpListener  listener = null;
        private static StreamReader reader = null;
        private static StreamWriter writer = null;
        private static List<Task>   clientTasks = new List<Task>();
        private static List<string> messages = new List<string>();

        public static void Main()
        {
            Console.Title = "Server";
            try
            {
                listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 8080);
                listener.Start();
                Console.WriteLine("Server started...");

                var connectTask = Task.Run(() => ConnectClients());
                //var listenTask = Task.Run(() => ListenClients());

                Task.WaitAll(connectTask);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
            finally
            {
                if (listener != null)
                {
                    listener.Stop();
                }
            }
        }

        private static void ConnectClients()
        {
            Console.WriteLine("Waiting for incoming client connections...");
            while (true)
            {
                if (listener.Pending()) //if someone want to connect
                {
                    clients.Add(new Client(listener.AcceptTcpClient(), "Client: " + (clients.Count + 1)));
                    Console.WriteLine(clients[clients.Count - 1].clientName + " connected to server.");
                    clientTasks.Add(Task.Run(() => HandleClient(clients[clients.Count - 1]))); //start new task for new client
                }
            }
        }

        private static void HandleClient(Client TCPClient)
        {
            string s = string.Empty;
            writer = new StreamWriter(TCPClient.client.GetStream());
            reader = new StreamReader(TCPClient.client.GetStream());

            try
            {
                while (!(s = reader.ReadLine()).Equals("Exit") || (s == null))
                {
                    if(!TCPClient.client.Connected)
                    {
                        Console.WriteLine("Client disconnected.");
                        clients.Remove(TCPClient);
                    }

                    Console.WriteLine("From client: " + TCPClient.clientName  + " -> " + s);
                    messages.Add(TCPClient.clientName + ": " + s); //save new message
                    //Console.WriteLine(s);

                    foreach (Client c in clients) //refresh all connected clients
                    {
                        c.writer.WriteLine("%C"); //clear client
                        foreach (string msg in messages)
                        {
                            c.writer.WriteLine(msg);
                            c.writer.Flush();
                        }
                    }
                }
                CloseServer();
            }
            catch (Exception e) { Console.WriteLine(e); }
        }

        private static void CloseServer()
        {
            reader.Close();
            writer.Close();
            clients.ForEach(tcpClient => tcpClient.client.Close());
        }
    }
}

I klasę pomocniczą, Client:

 

using System.Net.Sockets;
using System.IO;

namespace Server
{
    class Client
    {
        public TcpClient client;
        public StreamWriter writer;
        public string clientName;

        public Client(TcpClient client, string clientName)
        {
            this.client = client;
            writer = new StreamWriter(client.GetStream());
            this.clientName = clientName;
        }
    }
}


Klienci wysyłają wiadomości do serwera który przechowuje całą konwersację, po otrzymaniu wiadomości wysyła całą konwersację do wszystkich klientów odświeżając tym samym ich okna.

Program działa dobrze dla jednego klienta, ale kiedy mam dwóch, na początku działa ale gdy jeden klient wyśle wiadomość, a potem drugi wyśle to tak jakby jeden z klientów pisze za dwóch raz za jednego raz za drugiego a drugi nie może napisać nic.

1 odpowiedź

–1 głos
odpowiedź 17 kwietnia 2017 przez pulson666 Stary wyjadacz (12,560 p.)
myślę, że asynchroniczność rozwiąże Twój problem
komentarz 17 kwietnia 2017 przez timrh Mądrala (6,030 p.)
A więc czym są twoim zdaniem Taski?
komentarz 18 kwietnia 2017 przez pulson666 Stary wyjadacz (12,560 p.)
a faktycznie przeoczyłem to, moja wina.

Podobne pytania

–1 głos
1 odpowiedź 773 wizyt
0 głosów
1 odpowiedź 418 wizyt
pytanie zadane 11 czerwca 2022 w Java przez romilus Nowicjusz (120 p.)
+1 głos
1 odpowiedź 667 wizyt
pytanie zadane 7 stycznia 2018 w C i C++ przez Kapi2222 Obywatel (1,220 p.)

92,451 zapytań

141,261 odpowiedzi

319,073 komentarzy

61,853 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...