Асинхронный сервер - чат, много сообщений - C#

Узнай цену своей работы

Формулировка задачи:

вобщем сделал некое подобие чата, все вроде бы хорошо - отсылает/принимает сообщения нормально от множества клиентов придумал некую эмуляцию большой нагрузки
                            for (int i = 0; i < 100; ++i)
                            {
                                client.Send("test message " + i);
                                //Thread.Sleep(150);
                            }
в итоге сообщения сливаются в строки типа "test message 1test message 2test message 3" и т.д если включить Sleep и пробовать на 2 разных компах в сети глюк остается, но через 127.0.0.1 глюка нет а если без задержки то даже через 127.0.0.1 сливаются серверная часть часть выглядит так
    class AsyncServer
    {
        int port = 5691;
        object locker = new object();
 
        //IPHostEntry host;
        IPAddress addr;
        Socket _mainSocket;
        List<User> connections = new List<User>();
 
        public AsyncServer()
        {
            //host = Dns.GetHostEntry(Dns.GetHostName());
            //foreach (var v in host.AddressList)
            //  Console.WriteLine(v);
            
            addr = IPAddress.Loopback;//host.AddressList[3];
 
            SetServer();
            StartAsync();
        }
        private void SetServer()
        {
            _mainSocket = new Socket(addr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            _mainSocket.Bind(new IPEndPoint(addr, port));
            _mainSocket.Listen(10);
            Console.WriteLine("сервер запущен на {0}", _mainSocket.LocalEndPoint);
        }
 
        private void StartAsync()
        {
            for (int i = 0; i < 10; ++i)
                _mainSocket.BeginAccept(null, 1024, new AsyncCallback(AcceptCallback), _mainSocket);
        }
 
        private void AcceptCallback(IAsyncResult ar)
        {
            User _user = new User();
            _user.Buffer = new byte[256];
 
            try
            {
                Socket socket = (Socket)ar.AsyncState;
 
                int countBytes = -1;
                byte[] buff;
                _user.socket = socket.EndAccept(out buff, out countBytes, ar);
                if (countBytes > 0)
                {
                    string[] nameAndPass = Encoding.UTF8.GetString(buff, 0, countBytes).Split('&');
 
                    _user.uName = nameAndPass[0];
                    _user.uPassword = nameAndPass[1];
                }
 
                //Console.WriteLine("установленно соединение с {0}  {1} >> {2}",
                // _user.socket.RemoteEndPoint, _user.uName, _user.uPassword);
 
                lock (locker)
                    connections.Add(_user);
 
                _user.socket.BeginReceive(_user.Buffer, 0, _user.Buffer.Length,
                    SocketFlags.None, new AsyncCallback(ReceiveCallback), _user);
 
                socket.BeginAccept(null, 1024, new AsyncCallback(AcceptCallback), _mainSocket);
 
                SendSystemMMessage("Вошел в чат", _user);
            }
            catch (SocketException sExept)
            {
                Console.WriteLine(sExept.ErrorCode);
            }
            catch (SystemException ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
 
        private void ReceiveCallback(IAsyncResult ar)
        {
            User user = (User)ar.AsyncState;
 
            try
            {
                int bytesCount = user.socket.EndReceive(ar);
 
                if (bytesCount != 0) 
                {
                    string text = Encoding.UTF8.GetString(user.Buffer, 0, bytesCount);
 
                    if (text == "exit")
                    {
                        CloseConnect(user);
                        return;
                    }
 
                    Console.WriteLine(text);
 
                    lock (locker)
                        foreach (User client in connections)
                        {
                            client.socket.Send(user.Buffer, 0, bytesCount, SocketFlags.None);
                        }
                    user.socket.BeginReceive(user.Buffer, 0, user.Buffer.Length, SocketFlags.None,
                        new AsyncCallback(ReceiveCallback), user);
                }
                else CloseConnect(user);
 
            }
            catch (SocketException ex)
            {
                if (ex.ErrorCode == 10054)
                {
                    CloseConnect(user);
                    SendSystemMMessage("(SocketException) Вышел из чата ", user);
                }
            }
        }
 
        private void CloseConnect(User _user)
        {
            _user.socket.Close();
 
            lock (locker)
                connections.Remove(_user);
 
            SendSystemMMessage("Вышел из чата ", _user);
        }
 
        private void SendSystemMMessage(string msg, User from)
        {
            Console.WriteLine(from.uName + "  " + msg);
 
            byte[] tempBuf = Encoding.UTF8.GetBytes(string.Format("{0} " + msg, from.uName));
 
            lock (locker)
                foreach (var clinet in connections)
                    clinet.socket.Send(tempBuf, 0, tempBuf.Length, SocketFlags.None);
        }
 
        //private void SendCallback(IAsyncResult ar)
        //{
        //    ((Socket)ar.AsyncState).EndSend(ar);
        //}
 
        class User
        {
            public string uName;
            public string uPassword;
            public Socket socket;
            public byte[] Buffer;
        }
    }
бьюсь пол дня, чего только не пробовал уже - все равно сообщения сливаются... вот я думаю возможно ли это вообще вылечить? может такой поток сообщений и не должно выдерживать? да и кстати говоря - нормально ли делать такой прием имени юзера и пароля? выглядит как-то не очень надежно...как лучше?

Решение задачи: «Асинхронный сервер - чат, много сообщений»

textual
Листинг программы
while ((bytesRcvd = User.Receive(MessageBuffer, MessageBuffer.Length, SocketFlags.None)) > 0 && User.Connected) {
                    TotalBytes += bytesRcvd;
 
                    Random RND = new Random();//Симулируем лаги
                    int RNDNum = RND.Next(20000000);
                    for (int blabla = 0; blabla < 10000000 + RNDNum; blabla++) {
                        int gg = blabla;
                    }
 
                    Message = Encoding.UTF8.GetString(MessageBuffer, 0, bytesRcvd);
                    //Console.WriteLine(Message + " " + bytesRcvd);
                    String[] MessageArr = Message.Split('\0');
                    foreach (String TM in MessageArr) {
                        if (TM.Length > 0) {
                            Message = TM+"\0";
                            MessageData = Encoding.UTF8.GetBytes(Message);
 
                            Console.WriteLine(Message + " " + Message.Length + " " + bytesRcvd);

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

5   голосов , оценка 4.2 из 5
Похожие ответы