TCP / IP应用程序中的错误

时间:2017-04-18 12:34:27

标签: c# tcp client-server task-parallel-library tcp-ip

我写了一个客户端 - 服务器应用程序,这是许多客户端的控制台聊天应用程序。当只连接一个客户端时,应用程序运行良好,但是当连接两个或多个客户端时我有一个错误,在向第二个客户端发送一条消息后,他失去了与服务器的连接,只有第一个客户端可以向服务器...

我使用Task进行异步操作,如侦听端口和发送消息。当一个客户端向服务器发送消息时,它会将其添加到列表消息中并重新发送到所有客户端以刷新所有窗口。

服务器应用程序:

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.");
                    var newClientTask = Task.Run(() => HandleClient(clients[clients.Count - 1]));
                    clientTasks.Add(newClientTask); //start new task for new client
                }
            }
        }

        private static void HandleClient(Client TCPClient)
        {
            Console.WriteLine("Starting handle client");
            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); }
            Console.WriteLine("ending handle client");
        }

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

客户信息类:

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

客户申请:

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

            ConnectLoop();


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

        private static void ConnectLoop()
        {
            bool refreshTask = false;

            Task sendTask = null, recieveTask = null, updateConvTask = null;

            while (true)
            {
                if(!client.Connected) //try to connect
                {
                    refreshTask = true;
                    if(sendTask != null || recieveTask != null || updateConvTask != null)
                    {
                        sendTask.Dispose();
                        recieveTask.Dispose();
                        updateConvTask.Dispose();

                        sendTask = recieveTask = updateConvTask = null;
                    }

                    Console.WriteLine("Connecting to server...");

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

                    Thread.Sleep(10);
                }
                else if(refreshTask) // \/ CONNECTED \/
                {
                    Console.WriteLine("Connected.");

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

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

                    refreshTask = false;
                }
            }
        }

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

    }
}

我知道我的错误是愚蠢的。我是TCP / IP应用程序的新手,你能给我一些使用它和任务的教程的链接吗?

感谢您的帮助。

0 个答案:

没有答案