Я использую системный таймер таймера в консольном приложении прослушивателя асинхронного сокета.Я хочу, чтобы таймер запускался каждые 40 секунд и проверял состояние подключения клиентских устройств.
Как только таймер запускается, сокет сервера больше не прослушивает (не ожидает больше подключений), и только данные могут быть получены все время1-м устройством, которое было подключено.Когда я вынул устройство из сети и снова подключился, ничего не происходило.Никакая другая функция не работает.Вот код для таймера -
IPStatusTimer = new System.Timers.Timer(35000);
IPStatusTimer.Elapsed += IPStatusTimer_Elapsed;
IPStatusTimer.AutoReset = true;
IPStatusTimer.Enabled = true;
private static void IPStatusTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Console.WriteLine("Inside Timer");
if (connectedClient > 0)
{
foreach (KeyValuePair<string, int> i in IPStatus)
{
if (i.Value == 1)
{
IPStatus[i.Key] = 0;
}
else if (i.Value == 0)
{
Decode dr = new Decode();
string m = dr.offlineMessage();
if (Clients.Count > 0)
{
foreach (KeyValuePair<int, StateObject> c in Clients)
{
if (((IPEndPoint)c.Value.workSocket.RemoteEndPoint).Address.ToString() == i.Key)
{
Clients.Remove(c.Key);
}
}
SendMessage(i.Key, m);
}
}
}
}
}
Таймер не должен влиять на другие мои функции.Это должно спокойно работать в фоновом режиме, пока приложение не работает.
РЕДАКТИРОВАТЬ: (в приведенном выше коде) Добавлен, если CLients.Count> 0, то только удалит элемент из CLients, так что там не будет никаких исключений.
Всякий раз, когда есть соединение, которое я добавляюStateобъект для словаря, так что я могу транслировать данные всем клиентам, когда требуется.
public static void AcceptCallback(IAsyncResult ar)
{
connectedClient++;
// Signal the main thread to continue.
allDone.Set();
// Get the socket that handles the client request.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
string ip = ((IPEndPoint)handler.RemoteEndPoint).Address.ToString();
Console.WriteLine("ip " + ip);
// Create the state object.
StateObject state = new StateObject();
state.buffer = new byte[StateObject.BufferSize];
Clients.Add(connectedClient, state);
if (IPStatus.ContainsKey(ip))
IPStatus[ip] = 1;
else
IPStatus.Add(ip, 1);
Console.WriteLine(" Total Connected client : " + connectedClient);
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
Так, как вы можете видеть. Если клиент вернулся в сеть, а сервер всегда находится в режиме прослушивания, он должен принятьобъект соединения и состояния должен быть снова добавлен в клиент (объект словаря).Это не должно быть проблемой.И как только клиент подключается, я присваиваю IPStatus (объекту словаря) значение 1, поскольку это означает, что клиент находится в сети.
Затем в моем readCallBack () всякий раз, когда я получаю данные от любого клиента, затем в моем словаре, Я снова устанавливаю его значение на 1 в IPStatus.
public static void ReadCallback(IAsyncResult ar)
{
string content = string.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
int i = 0;
string ip = ((IPEndPoint)handler.RemoteEndPoint).Address.ToString();
if (IPStatus.ContainsKey(ip))
{
IPStatus[ip] = 1;
}
}
И когда таймер запускается, если значение любого IP равно 1, я устанавливаю его на 0. Так что в следующий раз, если таймер работает, и он получаетзначение 0 означает, что он не получил никаких данных от клиента за последние 35 секунд, что означает, что клиент больше не подключен к сети.ReadCallback и все происходит с использованием StateObject, а не с клиентами (dictinary Object).Поэтому, если я удаляю какой-либо элемент из клиентов, я добавляю его снова, когда начинается любое новое соединение.
Надеюсь, мой сценарий станет более понятным для вас, ребята.