Asynchroniczny klient,serwer TCP dla wielu klientów

0

Cześć

Chce napisać aplikacje klient-serwer która będzie działała asynchronicznie na wielu użytkowników lecz przy próbie połączenia się z serwerem dostaje wyjątek:

  • Nie można nawiązać połączenia, ponieważ komputer docelowy aktywnie go odmawia**

Nie wiem gdzie leży problem dlatego zwracam się do was o pomoc

Serwer:

public class Server
    {
        private static TcpListener _listener;

        public static string GetMyIp()
        {
            var host = Dns.GetHostEntry(Dns.GetHostName());
            foreach (var ip in host.AddressList)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    return ip.ToString();
                }
            }
            throw new Exception("Nie znaleziono Ip");
        }

        public static void StartServer()
        {
            IPAddress localIp = IPAddress.Parse(GetMyIp());
            IPEndPoint myLocalIp = new IPEndPoint(localIp,5000);
            _listener = new TcpListener(myLocalIp);
            _listener.Start();
            NewClientConnected();
            Console.WriteLine("Serwer uruchomiony");
        }

        private static void NewClientConnected()
        {
            object obj = new object();
            _listener.BeginAcceptTcpClient(new AsyncCallback(OnClientConnect), obj);
        }

        private static void OnClientConnect(IAsyncResult asyncResult)
        {
            try
            {
                TcpClient socket = default(TcpClient);
                socket = _listener.EndAcceptTcpClient(asyncResult);
                ClientRequestHandler client = new ClientRequestHandler(socket);
                client.RunClient();
                
            }
            catch (Exception)
            {
                
                throw;
            }

            NewClientConnected();
        }
    }
}
 

Klient:

 public class Client
    {
        TcpClient clientSocket = new TcpClient();
        NetworkStream _serNetworkStream;


        public static string GetMyIp()
        {
            var host = Dns.GetHostEntry(Dns.GetHostName());
            foreach (var ip in host.AddressList)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    return ip.ToString();
                }
            }
            throw new Exception("Nie znaleziono Ip");
        }

        public void ConnectToRunningServer()
        {

            clientSocket.Connect(GetMyIp(), 5000);
        }

        public void SendMessage(string messageToSend)
        {
            if (!string.IsNullOrEmpty(messageToSend))
            {
                NetworkStream serverNetworkStream = clientSocket.GetStream();
                byte[] outData = Encoding.ASCII.GetBytes(messageToSend);
                serverNetworkStream.Write(outData,0, outData.Length);
                serverNetworkStream.Flush();
            }
        }

        public void CloseConnection()
        {
            clientSocket.Close();
        }

        public string ReceiveMessages()
        {
            StringBuilder msg = new StringBuilder();
            NetworkStream serverNetworkStream = clientSocket.GetStream();
            serverNetworkStream.ReadTimeout = 100;
            bool isRunning = true;
            while (isRunning)
            {
                if (serverNetworkStream.DataAvailable)
                {
                    int readData = serverNetworkStream.ReadByte();
                    if (readData > 0)
                    {
                        msg.Append((char) readData);
                    }
                    else
                    {
                        break;                        
                    }
                }
                else if (msg.ToString().Length > 0)
                {
                    isRunning = false;
                }
            }
            return msg.ToString();
        }
    }
 

Będę wdzięczny za każdą pomoc

0

Jest 2016 rok, zamiast tych AsyncCallbacków mógłbyś skorzystać jak człowiek z async-await.

0

Zastosowałem podejście async-await, i po wysłaniu wiadomości po stronie klienta dostaje exception:
Nawiązane połączenie zostało przerwane przez oprogramowanie zainstalowane w komputerze-hoście

Serwer:

 
 public class Server
    {
        static object _locking = new object();
        static List<Task> _connectList = new List<Task>();

        public static Task StartListen()
        {
            return Task.Run(async () =>
            {
                var tcpListener = TcpListener.Create(8000);
                tcpListener.Start();
                while (true)
                {
                    var tcpClient = await tcpListener.AcceptTcpClientAsync();
                    Console.WriteLine("Server: Klient połączył sie z serwerem");
                    var task = ClientRequestHandler(tcpClient);
                    if (task.IsFaulted)
                        task.Wait();
                }
            });
        }

        public static async Task ClientRequestHandler(TcpClient tcpClient)
        {
            var connectionTask = HandleConnectionAsync(tcpClient);

            lock (_locking)
                _connectList.Add(connectionTask);

            try
            {
                await connectionTask;
            }
            catch (Exception ex)
            {

                Console.WriteLine(ex.ToString());
            }
            finally
            {
                lock (_locking)
                    _connectList.Remove(connectionTask);
            }
        }

        public static Task HandleConnectionAsync(TcpClient tcpClient)
        {
            return Task.Run(async () =>
            {
                using (var networkStream = tcpClient.GetStream())
                {
                    var buffer = new byte[4096];
                    Console.WriteLine("Server: Odczytywanie wiadomości do klienta");
                    var byteCount = await networkStream.ReadAsync(buffer, 0, buffer.Length);
                    var request = Encoding.UTF8.GetString(buffer, 0, byteCount);
                    Console.WriteLine("[Server: Klient napisał: {0}", request);
                    var serverResponseBytes = Encoding.UTF8.GetBytes("*" + request);
                    await networkStream.WriteAsync(serverResponseBytes, 0, serverResponseBytes.Length);

                }
            });
        }
    }

Klient:

 
 public class AsyncClient
    {
        public static string GetMyIp()
        {
            var host = Dns.GetHostEntry(Dns.GetHostName());
            foreach (var ip in host.AddressList)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    return ip.ToString();
                }
            }
            throw new Exception("Nie znaleziono Ip");
        }

        public static async Task StartClient()
        {
            await Task.Yield();

            Console.WriteLine("Connecting " + GetMyIp());
            StreamReader sr = null;
            StreamWriter sw = null;
            try
            {
                TcpClient tcpClient = new TcpClient();
                await tcpClient.ConnectAsync(GetMyIp(), 8000);
                var stream = tcpClient.GetStream();
                sr = new StreamReader(stream, Encoding.UTF8);
                sw = new StreamWriter(stream, Encoding.UTF8);
                while (tcpClient.Connected)
                {
                    await sw.WriteLineAsync("Dzien dobry");
                    await sw.FlushAsync();
                    var msg = await sr.ReadLineAsync();
                }
            }
            catch (Exception aex)
            {
                var ex = aex.GetBaseException();
                Console.WriteLine("Client error: " + ex.Message);
            }
            finally
            {
                if (sr != null)
                    sr.Dispose();
                if (sw != null)
                    sw.Dispose();
            }
            Console.WriteLine("Disconnecting " + GetMyIp());

        }
    }

Błąd:
user image

Próbowałem tez połączyć się i wysłać wiadomość przez telnet to zaraz po wprowadzeniu jednej literki zostaje ona wysłana i połączenie przerwane...

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