Асинхронный сервер - чат, много сообщений - 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);