Асинхронный сервер - чат, много сообщений - 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);
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д