Получение ip устройства при неудачном запросе Ping.SendAsync - C#
Формулировка задачи:
Всем привет! Надеюсь, вы поможете найти решение моей проблемы...
Цели создаваемой программы: 1) ping одного устройства по запросу пользователя; 2) ping группы устройств по таймеру.
Суть проблемы: если использовать обычный Ping.Send программа виснет намертво при множественных запросах пинга и наличии недоступных устройств. Поэтому решила использовать асинхронный пинг
Ping.SendAsync
. Теперь проблема в том, чтоPingReply
, возвращаемый при неудачном пинге содержит нулевые параметры и, соответственно, адрес 0.0.0.0. Как мне в обработчикеpingSender_Complete
получить адрес, который программа пыталась пинговать? Сейчас в коде я использую глобальную переменннуюcurrentUSK
, но в случае группового пинга, когда все результаты появляются с разной задержкой, они, естественно, получают самое последнее значение этой переменной. Можно ли адрес или весь объектUSK
передать в обработчик события? Информации на доступном для меня уровне в интернете не нашла. Подскажите, куда копать?namespace PingUSK
{
/// <summary>
/// Логика взаимодействия для MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
//глобальные переменные
public static String connectStr;
FbConnection connection = new FbConnection(connectStr);
FbCommand command = new FbCommand();
FbDataAdapter dataAdapter = new FbDataAdapter();
DataTable dt = new DataTable();
List<USK> list_of_USK = new List<USK>();
//поток записи и чтения
StreamWriter sw;
StreamReader sr;
//файл
FileInfo aFile;
USK currentUSK = new USK();
ObservableCollection<resPing> log = new ObservableCollection<resPing>();
System.Threading.Timer tm;
AutoResetEvent resetEvent = new AutoResetEvent(false);
public MainWindow()
{
InitializeComponent();
// получаю список УСК
GetUSK();
//заполняю комбобокс значениями из списка УСК
foreach (var item in list_of_USK)
{
comboBox1.Items.Add(item.abonent + " | " + item.ip + " | " + item.address);
}
comboBox1.SelectedIndex = 0;
//создание текстового файла с базой или его открытие
aFile = new FileInfo("d:\\PingUSK.txt");
if (aFile.Exists == false) { aFile.Create(); }
//чтение из файла, вывод в листбокс
sr = aFile.OpenText();
while (!sr.EndOfStream)
{
try
{
String str = sr.ReadLine();
String[] mas = str.Split('|');
log.Add(new resPing() { id = Convert.ToInt32(mas[0]), abonent = mas[1], address = mas[2], ip = mas[3], time = Convert.ToInt32(mas[4]), status = mas[5], date = Convert.ToDateTime(mas[6]), buf=Convert.ToInt32(mas[7]), TTL=Convert.ToInt32(mas[8]) });
}
catch { }
}
sr.Close();
dataGrid1.ItemsSource = log;
dataGrid1.Items.Refresh();
try
{
dataGrid1.Items.MoveCurrentToLast();
dataGrid1.ScrollIntoView(dataGrid1.SelectedItem);
}
catch { }
//запуск таймера
tm = new System.Threading.Timer(Callback, null, new TimeSpan(0, 1, 0), new TimeSpan(0, 1, 0));
}
// процедура, выполняемая при срабатывании таймера (коллективный пинг)
private void Callback(object param)
{
foreach (var item in list_of_USK)
{
try
{
Dispatcher.BeginInvoke(DispatcherPriority.Send, (Action<USK>)PingForCircle, item);
}
catch { }
}
}
// пинг одного устройства (на выбор пользователя)
public void JustPing()
{
Int32 i = comboBox1.SelectedIndex;
USK cur = list_of_USK[i];
currentUSK = cur;
SendPing(cur);
}
// массовый пинг
public void PingForCircle(USK usk)
{
currentUSK = usk;
SendPing(usk);
}
private void SendPing(USK _cur)
{
USK cur = _cur;
Ping pingSender = new System.Net.NetworkInformation.Ping();
// событие при завершении пинга
pingSender.PingCompleted += new PingCompletedEventHandler(pingSender_Complete);
// установки
byte[] packetData = Encoding.ASCII.GetBytes("................................");
PingOptions packetOptions = new PingOptions(50, true);
pingSender.SendAsync(cur.ip, 2000, packetData, packetOptions, resetEvent); //посылка асинхронного пинга
}
private void pingSender_Complete(object sender, PingCompletedEventArgs e)
{
if (e.Cancelled)
{
((AutoResetEvent)e.UserState).Set();
}
else if (e.Error != null)
{
MessageBox.Show("An error occured: " + e.Error + "\r\n");
((AutoResetEvent)e.UserState).Set();
}
else
{
PingReply pingResponse = e.Reply;
// вызов процедуры вывода результатов
ShowPingResults(pingResponse);
}
}
public void ShowPingResults(PingReply pingResponse)
{
String adr = pingResponse.Address.ToString();
USK getUSK = new USK();
// поиск уск в списке по ip
foreach (var item in list_of_USK)
{
if (item.ip == adr) { getUSK = item; break; }
}
//если пинг неудачный...
if (pingResponse.RoundtripTime == 0)
{
log.Add(new resPing() { id = Convert.ToInt32(getUSK.id), abonent = getUSK.abonent, address = getUSK.address, ip = getUSK.ip, time = Convert.ToInt32(pingResponse.RoundtripTime.ToString()), status = pingResponse.Status.ToString(), date = DateTime.Now, buf = pingResponse.Buffer.Length, TTL = 0 });
dataGrid1.Items.Refresh();
dataGrid1.Items.MoveCurrentToLast();
dataGrid1.ScrollIntoView(dataGrid1.SelectedItem);
sw = aFile.AppendText();
sw.WriteLine(getUSK.id + "|" + getUSK.abonent + "|" + getUSK.address + "|" + getUSK.ip + "|" + pingResponse.RoundtripTime + "|" + pingResponse.Status + "|" + DateTime.Now + "|" + pingResponse.Buffer.Length + "|" + "0");
sw.Close();
}
// если пинг прошел...
else
{
log.Add(new resPing() { id = Convert.ToInt32(getUSK.id), abonent = getUSK.abonent, address = getUSK.address, ip = getUSK.ip, time = Convert.ToInt32(pingResponse.RoundtripTime.ToString()), status = pingResponse.Status.ToString(), date = DateTime.Now, buf = pingResponse.Buffer.Length, TTL = pingResponse.Options.Ttl });
dataGrid1.Items.Refresh();
dataGrid1.Items.MoveCurrentToLast();
dataGrid1.ScrollIntoView(dataGrid1.SelectedItem);
sw = aFile.AppendText();
sw.WriteLine(getUSK.id + "|" + getUSK.abonent + "|" + getUSK.address + "|" + getUSK.ip + "|" + pingResponse.RoundtripTime + "|" + pingResponse.Status + "|" + DateTime.Now + "|" + pingResponse.Buffer.Length + "|" + pingResponse.Options.Ttl);
sw.Close();
}
}
public void GetUSK() //формируем список уск с помощью запросов к БД
{
String comm = "";
connectStr = @"User=***;Password=***;Database=D:\Program Files (x86)\ASDK\DB\firenet.GDB;DataSource=***; Port=***;Dialect=3; Charset=NONE;Role=;Connection lifetime=15;Pooling=true; MinPoolSize=0;MaxPoolSize=50;Packet Size=8192;ServerType=0;";
connection.ConnectionString = connectStr;
command.Connection = connection;
comm = "SELECT U.USK_ID, A.AB_NAME, U.USK_ADR_ID, U.USK_IP FROM USK U, ABONENT A WHERE U.USK_AB_ID=AB_ID AND (U.USK_TYPE=2 OR U.USK_TYPE=1 OR U.USK_TYPE=3)";
command.CommandText = comm;
connection.Open();
FbDataReader r = command.ExecuteReader();
while (r.Read())
{
USK curUSK = new USK();
curUSK.id = r.GetString(0);
curUSK.abonent = r.GetString(1);
curUSK.address_id = r.GetString(2);
curUSK.ip = r.GetString(3);
list_of_USK.Add(curUSK);
}
connection.Close();
foreach (var item in list_of_USK)
{
comm = "SELECT ADR_STR FROM WP_GET_ADRESS(" + item.address_id + ",3)";
command.CommandText = comm;
connection.Open();
FbDataReader rr = command.ExecuteReader();
while (rr.Read())
{
item.address = rr.GetString(0);
}
connection.Close();
}
}
private void button1_Click(object sender, RoutedEventArgs e)
{
JustPing(); // вызов пинга для одного уск
}
}
//контейнер для УСК (первоначальная инфа из базы)
public class USK
{
public String id;
public String abonent;
public String ip;
public String address_id;
public String address;
}
// контейнер результатов ping'а
public class resPing
{
public Int32 id {get; set;}
public String abonent{get; set;}
public String ip { get; set; }
public String address { get; set; }
public String status { get; set; }
public Int32 time { get; set; }
public DateTime date { get; set; }
public Int32 buf { get; set; }
public Int32 TTL { get; set; }
}
//конвертер статуса в кисть
class StatusToColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (String)value != "Success" ?
new SolidColorBrush(Colors.Red)
: new SolidColorBrush(Colors.White);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new Exception("The method or operation is not implemented.");
}
}
}Решение задачи: «Получение ip устройства при неудачном запросе Ping.SendAsync»
textual
Листинг программы
public void SendAsync(IPAddress address, int timeout, byte[] buffer, PingOptions options, Object userToken)