Асинхронный сервер - чат, много сообщений - C#
Формулировка задачи:
вобщем сделал некое подобие чата, все вроде бы хорошо - отсылает/принимает сообщения нормально от множества клиентов
придумал некую эмуляцию большой нагрузки
в итоге сообщения сливаются в строки типа "test message 1test message 2test message 3" и т.д
если включить Sleep и пробовать на 2 разных компах в сети глюк остается, но через 127.0.0.1 глюка нет
а если без задержки то даже через 127.0.0.1 сливаются
серверная часть часть выглядит так
бьюсь пол дня, чего только не пробовал уже - все равно сообщения сливаются...
вот я думаю возможно ли это вообще вылечить? может такой поток сообщений и не должно выдерживать?
да и кстати говоря - нормально ли делать такой прием имени юзера и пароля? выглядит как-то не очень надежно...как лучше?
for (int i = 0; i < 100; ++i) { client.Send("test message " + i); //Thread.Sleep(150); }
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);
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д