(SOFT) SOFT (2009 год)

Xping - утилита контроля качества связи

С тех пор, как выборы у нас стали считаться формой экстремизма - качество интернет-связи в Москве упало невероятно. Для примера возьмем лучший московский датацентр Hoster.ru (это сказано без иронии - я действительно так думаю, о худших я скажу дальше). Давайте взглянем на трассировку канала к некому серверу, находящемуся на нем. Результаты впечатляют. Сначала на 38 мс подвисла крупная магистраль по Москве gldn.net на допотопном кабеле категории 04, потом на 56 мс подвис шлюз на входе в эту же магистраль, потом аж на 184 мс подвис шлюз на выходе этой магистрали на Hoster.ru и одновременно вовремя шлюз внутри Hoster.ru не принял ответа от целевого сервера. Дальше больше - по самому Hoster.ru пакет cтал проходить к целевому серверу через откуда-то взявшийся сначала девятый шлюз, а потом и через десятый.




Что же говорить о худших датацентрах? Вот трасса к небольшому хостингу itsoft.ru, находящемуся в районе Фили. Скорость прохождения пакета здесь стабильна - вот только ходят пакеты туда из центра Москвы дольше, чем до Лондона.




Многие подмосковные хостинги, такие как Agava.ru - расположены как будто бы на другой планете. Например пакет по той же самой допотопной магистрали категории 4 прошел в направлении к Агаве за 310 мс, затем подвис на 48 мс на той же крупной магистрали gldn.net. Затем пакет вышел на междугороднюю связь Москва-Долгопрудный, который прошел аж за 121 мс. И затем три шлюза по Долгопрудному по 21 мс. Для сравнения, я взял город за 1000 километров от Москвы. Как видите, там всего два шлюза по 35 и один шлюз видимо в самом датацентре Белгорода.

То есть до Белгорода - около 100 мс, а до Долгопрудного - 600 мс. По-моему как раз за такое время сигнал доходит до Луны и обратно.




Но это лишь одна грань вопроса - собственно качество каналов связи у нас в Москве. Есть и другая грань - откровенный беспредел интернет-провайдеров в отношении частных потребителей. Вызван он ровно теми же причинами, что и качество каналов связи - всеобщим бардаком и коррупцией (крышеванием "правоохранителями" крупных игроков телекоммуникационного рынка). И, соответственно, пониманием крупными игроками абсолютной своей безнаказанности по отношении к гражданам, конечным потребителям их услуг.

Опять же, наверное, нет смысла говорить о худших - поговорим о лучших, например о самом быстром в Москве провайдере Corbina Telecom. Вот до какого состояния надо довести человека, чтобы он написал вот такое письмо? Учитывая что все-таки к дому подходит всего-то два провайдера.




В течении месяца как минимум я не смог добиться, чтобы оплаченный мною внешний айпишник был достижим и видим из интернета.




При этом я почти каждый день звонил и уговаривал их. Предлагал сам подъехать к ним и настроить им шлюз. Бесполезно.




Любопытно выглядит даже переписка с Corbina telecom. Например я создаю заявку на Support. В ней первой же фразой указываю, что прошивка именно та, которая рекомендована корбиной и сгружена именно с сайта Корбины. Ответ приходит интересный - с рекомендацией прошить фаервол тем, чем он и был прошит. А надо сказать, что со стандартной прошивкой роутеров корбина почему-то работать не умеет. Подключение возможно лишь через несколько весьма специфичных и странных устройств, которые рекомендованы на этой страничке. Непонятно, если я ко всем коннекчусь с помощью ZyWall 70 - и привык с ним работать - почему нельзя поднять на VPN-сервере обычный стандартный PPPOE или обычный стандартный PPPTP? Ведь это же крупная фирма - Билайн. Неужели нет денег на стандартный VPN-сервер? Но мне хотелось подключиться к этому быстрому провайдеру и я приобрел сначала одно это странное малопроизводительное устройство, а потом и второе. Естественно, без особой нестандартной прошивки к странному корбиновскому VPN они не коннектятся. Естественно, если я вообще получаю хоть что-то, и коннект падает - значит устройства уже перепрошиты. В противном случае - ничего внутри тоннеля получить в принципе невозможно. Собственно об этом - первая фраза моей заявки на суппорт. В ответ на эту заявку получаю чудо-ответ с предложением перепрошить свой роутер прошивкой с сайта. Я в ответе я пишу суппорту, что ведь роутер/фаервол как раз этой прошивкой и прошит - в этом и суть заявки на суппорт. Немного напоминает разговор глухого со слепым, не правда ли? После этого замечания разговор красиво заходит в тупик. Мое замечание с первоначальной заявкой перекодируется и возвращается вместе с ответом в виде абракадабры. На это уже ничего ответить невозможно в принципе - ну как бы Yahoo отработало неверно и я сам виноват, что не прочитал умного совета корбиновского чудо-суппорта. Дальше делай что хочешь - деньги ты заплатил, суппорт вроде-бы обработал заявку о проблеме и ответил, а стабильного интернет-канала как не было - так и нет.

А ведь Корбина - это лучший интернет-провайдер. У него хотя бы прямой канал (от интернета к клиенту) рвался, но был. А по поводу худших интернет-провайдеров (которые не то что со внешним айпишником, но вообще выход в интернет наладить не могли) я даже написал жалобу в федеральную инспекцию электросвязи. Приложил неопровержимые доказательства, что интернет у них на канале был всего два-три для в неделю (!). И за период двух месяцев ни разу не было интернета более 4 дней в неделю.

Ответ пришел из Правительства Москвы. В ответе было указано, что эти линии связи правительству Москвы не принадлежат и лицензию у Акадо отозвать невозможно. Мое заявление перепроверялось 17.06.2008 и 18.06.2008. Какие-то проверяющие мое заявление барышни многократно перезванивали и им и мне в эти дни. Все равно Акадо не удалось поднять интернет в Жулебино хотя бы на момент проверки. Ну никак не удалось! Правда получать деньги от абонентов в Жулебино им эта мелочь не помешала.

Ах, бедное Акадо! Могу себе представить как бульдозер ездит взад-вперед по их кабелям, а доблестные работники Акадо с лопатами и паяльниками только и делают что починяют и починяют свои кабели. И занимаются этим нужным и благородным делом непрерывно - 3-4 дня каждую неделю! А проклятые бульдозеры рвут и рвут их кабели - даже в те дни, когда их деятельность проверяет Комиссия московского правительства!





Думаю, историю о качестве связи в Москве можно было бы продолжать бесконечно. Согласитесь, было бы удивительно, если бы взрывалась Саяно-Шушенская ГРЭС, тонули бы подводные лодки Курск, горели бы Останкинские телебашни, Евсюковы бы расстреливали людей в универсамах, ежедневно сотни тысяч человек бы стояли в Москве пробке (а в метро уже 140 человек с начала года просто задавили в давке), киллеров-отравителей, слегка отряхнувших с рук Полоний-210, принимали бы работать депутатами Государственной думы, взрывались бы жилые дома, а подрывателей бы ловили в Рязани и отпускали с миром, TV ежедневно крутило ролики бы о возрождении и величии нации в стиле Муссолини (позабыв как ответил Муссолини за свои речи "Вперед Италия" и "Италия поднимается с колен"), детей в Беслане срочно бы расстреливали из танков - потому что Масхадов обещал приехать и убрать террористов из школы, руководители ведомства борьбы с наркотиками скончались бы в сауне (находившейся прямо в их рабочем офисе) от передозировки, ежедневно люди продолжали бы погибать на маленькой победоносной войне на Кавказе, закрылся бы Москвич и АвтоВаз, а НКВД-ФСБ перешло на ношение черной гестаповской формы, кремлевские карлики активизировались бы и под шумок безнаказанно отнимали бы миллиарды долларов у Ходорковского и телеканалы у Гусинского, сынок какого-нибудь сосковца мог бы насмерть задавить четырех человек и получить только выговор от отца за помятый бампер, московскй мэр понимал бы поддержку предпринимательства как выделение собственной жене 1300 гектаров земли под застройку в Москве, суды бы давали сроки за убийство (офицера-подводника Пуманэ) в размере четырех месяцев условно, обрушивались бы аквапарки, самолеты и вертолеты, травили бы газом заложников Норд-Оста, в разрар кризиса разгоняли бы крупнейшие в стране мелкооптовые рынки, избирательные комиссии заявляли бы что в поддержку Едра проголосовало 114 процентов от проживающих в Дагестане, а 106 процентов подписей, поданных за Солидарность являются фальшивыми и так далее и так далее и так далее, но... - но во всей этой фантасмагории интернет-линии связи прекрасно бы работали! И провайдеры интернет-услуг наперегонки спешили удовлетворить потребителей своих услуг. Согласитесь - это нереально.

В интернете все обстоит ровно так же, как и везде. Сигнал от Москвы до Белгорода доходит за 100 мс, до Филей за 180 мс, а до Долгопрудного за 600 мс. Дойдя же наконец до нужного Датацентра, сигнал вообще забывает куда он пришел и начинает бродить в нем кругами 500-700-1800 мс, пока не вспомнит к какому серверу он пришел.

А почему нет? Почему электронный импульс должен вести себя во всей этой окружающей фантасмагории иначе? Ведь у нас даже молнии спокойно проходят двойную-тройную молниезащиту и спокойно поджигают нефтеперкачиващие станции - причем они сделали это минимум дважды за последний месяц (22 августа в Конге или 26 августа в БузулукНефти).

Сделать со всем этим безобразием, конечно же, нельзя ничего. Но можно хотя бы зафиксировать его. И для себя лично попытаться подобрать что-то лучшее из худшего.


Именно для этой цели существует моя утилитка Xping, которая в отличие от стандартной умеет запоминать все в базу. Запоминается все довольно экономно - одного винчестера хватит на много лет. К тому же вы в любой момент можете ее переделать для своих нужд, тк ее исходный код перед вами:


   1:  Module Module1
   2:   
   3:      Sub Main(ByVal args() As String)
   4:          Dim TimeountInterval As Integer = 1000 '1 sec
   5:          Dim SleepTime As Integer = 10000 '10 sec
   6:          Dim IpAddr As String '= "89.188.102.246" or "SQL.RU"
   7:          Dim ToSql As Boolean = False
   8:          Dim CN As Data.SqlClient.SqlConnection
   9:          Dim CMD As SqlClient.SqlCommand
  10:          Try
  11:              If args.Length = 0 Then
  12:  help1:
  13:                  Console.WriteLine("Usage: IpAddress SleepTimeSecond TimeountSecond")
  14:                  Console.WriteLine("Usage: 82.199.96.143 10 1")
  15:                  Console.WriteLine("or")
  16:                  Console.WriteLine("Usage: SQL.RU SleepTimeSecond TimeountSecond")
  17:                  Console.WriteLine("Ответ  82.199.96.143 ждем секунду, повторяем каждые 10 секунд")
  18:                  Console.WriteLine("SleepTimeSecond, TimeountSecond можно опустить")
  19:                  Console.WriteLine("В ответе: TTL - Time to Live, RTT - Round Trip time")
  20:                  Console.WriteLine("or")
  21:                  Console.WriteLine("Usage: SQL.RU SleepTimeSecond TimeountSecond /ToSQL")
  22:                  Console.WriteLine("Ответ пишется в базу, SqlConnectionString задан в Xping.config")
  23:                  Console.WriteLine("CREATE TABLE [dbo].[Xping](")
  24:                  Console.WriteLine("    [i] [int] IDENTITY(1,1) NOT NULL,")
  25:                  Console.WriteLine("    [IP] [nvarchar](50) NULL,")
  26:                  Console.WriteLine("    [Status] [int] NULL,")
  27:                  Console.WriteLine("    [Time] [datetime] NULL,")
  28:                  Console.WriteLine("    [TTL] [int] NULL,")
  29:                  Console.WriteLine("    [RTT] [int] NULL,")
  30:                  Console.WriteLine("    [Message] [nvarchar](max) NULL,")
  31:                  Console.WriteLine(" CONSTRAINT [PK_Ping] PRIMARY KEY CLUSTERED ")
  32:                  Console.WriteLine("(")
  33:                  Console.WriteLine("    [i] ASC")
  34:                  Console.WriteLine(")WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]")
  35:                  Console.WriteLine(") ON [PRIMARY]")
  36:                  Console.WriteLine("GO")
  37:                  Console.ReadLine()
  38:                  Exit Sub
  39:              ElseIf args.Length = 1 Then
  40:                  IpAddr = GetIpAddr(args(0))
  41:              ElseIf args.Length = 2 Then
  42:                  IpAddr = GetIpAddr(args(0))
  43:                  SleepTime = CInt(args(1)) * 1000
  44:              ElseIf args.Length = 3 Then
  45:                  IpAddr = GetIpAddr(args(0))
  46:                  SleepTime = CInt(args(1)) * 1000
  47:                  TimeountInterval = CInt(args(2)) * 1000
  48:              ElseIf args.Length = 4 Then
  49:                  IpAddr = GetIpAddr(args(0))
  50:                  SleepTime = CInt(args(1)) * 1000
  51:                  TimeountInterval = CInt(args(2)) * 1000
  52:                  ToSql = True
  53:              Else
  54:                  GoTo Help1
  55:              End If
  56:              '
  57:              Console.WriteLine(IpAddr & " (TTL - Time to Live, RTT - Round Trip time)")
  58:              Console.WriteLine()
  59:              '
  60:              If ToSql Then
  61:                  CN = New Data.SqlClient.SqlConnection(My.Settings.SqlConnectionString)
  62:                  Try
  63:                      CN.Open()
  64:                  Catch ex As Exception
  65:                      Console.WriteLine(ex.Message)
  66:                  End Try
  67:                  Try
  68:                      CMD = New SqlClient.SqlCommand(My.Settings.WriteCMD, CN)
  69:                      CMD.Parameters.AddWithValue("@IP", IpAddr)
  70:                      CMD.Parameters.Add("@Status", SqlDbType.Int)
  71:                      CMD.Parameters.Add("@TTL", SqlDbType.Int)
  72:                      CMD.Parameters.Add("@RTT", SqlDbType.Int)
  73:                      CMD.Parameters.Add("@Message", SqlDbType.NVarChar)
  74:                  Catch ex As Exception
  75:                      Console.WriteLine(ex.Message)
  76:                  End Try
  77:              End If
  78:              '
  79:              Dim Xping As New System.Net.NetworkInformation.Ping
  80:              Dim ANSI As New System.Text.ASCIIEncoding
  81:              '
  82:              While True
  83:                  Dim Replay As System.Net.NetworkInformation.PingReply = Xping.Send(IpAddr, TimeountInterval)
  84:                  If Replay.Status = Net.NetworkInformation.IPStatus.Success Then
  85:                      Console.WriteLine("TTL=" & Replay.Options.Ttl & ", " & "RTT=" & Replay.RoundtripTime & ", Time=" & Now.ToString) '& ", ReplayBuff=" & ANSI.GetString(Replay.Buffer))
  86:                      If ToSql Then
  87:                          CMD.Parameters("@Status").Value = 0
  88:                          CMD.Parameters("@TTL").Value = Replay.Options.Ttl
  89:                          CMD.Parameters("@RTT").Value = Replay.RoundtripTime
  90:                          CMD.Parameters("@Message").Value = "OK"
  91:                          CMD.ExecuteNonQuery()
  92:                      End If
  93:                  Else
  94:                      Console.WriteLine("Status=" & Replay.Status.ToString)
  95:                      If ToSql Then
  96:                          CMD.Parameters("@Status").Value = Replay.Status
  97:                          CMD.Parameters("@TTL").Value = -1
  98:                          CMD.Parameters("@RTT").Value = -1
  99:                          CMD.Parameters("@Message").Value = Replay.Status.ToString
 100:                          CMD.ExecuteNonQuery()
 101:                      End If
 102:                  End If
 103:                  System.Threading.Thread.Sleep(SleepTime)
 104:              End While
 105:          Catch ex As Exception
 106:              Console.WriteLine(ex.Message)
 107:              Console.ReadLine()
 108:          End Try
 109:   
 110:   
 111:      End Sub
 112:   
 113:      Function GetIpAddr(ByVal Str1 As String) As String
 114:          If Str1 <> "" Then
 115:              'определим это адрес или имя сначала
 116:              Dim Tst1() As String
 117:              Tst1 = Str1.Split(".")
 118:              If Tst1.Length = 4 Then
 119:                  If IsNumeric(Tst1(0)) And IsNumeric(Tst1(1)) And IsNumeric(Tst1(2)) And IsNumeric(Tst1(3)) Then
 120:                      Return Str1
 121:                  Else
 122:                      GoTo DNS
 123:                  End If
 124:              Else
 125:  DNS:            Dim IP_String As New Text.StringBuilder
 126:                  Dim DNS As System.Net.IPHostEntry
 127:                  DNS = System.Net.Dns.GetHostEntry(Str1)
 128:                  For Each One As System.Net.IPAddress In DNS.AddressList
 129:                      Dim IP_Bytes As Byte()
 130:                      IP_Bytes = One.GetAddressBytes()
 131:                      For i As Integer = 0 To IP_Bytes.Length - 1
 132:                          IP_String.Append(String.Format("{0:D2}.", IP_Bytes(i)))
 133:                      Next
 134:                      IP_String.Length -= 1
 135:                      'возвращается только первый IP адрес - наверное для кластера их может быть несколько
 136:                      Return (IP_String.ToString)
 137:                  Next
 138:              End If
 139:          Else
 140:              Throw New Exception("Address not set")
 141:          End If
 142:      End Function
 143:   
 144:  End Module

Код прошу строго не судить - написан он на одном дыхании ровно за час. Но дело свое делает:




У проги есть стандартный NET-овский конфиг, в котором надо пределелить коннект к базе и там же лежит комманда записи в базу:


   1:  <?xml version="1.0" encoding="utf-8" ?>
   2:  <configuration>
   3:      <configSections>
   4:          <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
   5:              <section name="Xping.My.MySettings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
   6:          </sectionGroup>
   7:      </configSections>
   8:      <connectionStrings>
   9:          <add name="Xping.My.MySettings.SqlConnectionString" connectionString="Data Source=.;Initial Catalog=Xping;Integrated Security=True" />
  10:      </connectionStrings>
  11:      <system.diagnostics>
  12:          <sources>
  13:              <!-- This section defines the logging configuration for My.Application.Log -->
  14:              <source name="DefaultSource" switchName="DefaultSwitch">
  15:                  <listeners>
  16:                      <add name="FileLog"/>
  17:                      <!-- Uncomment the below section to write to the Application Event Log -->
  18:                      <!--<add name="EventLog"/>-->
  19:                  </listeners>
  20:              </source>
  21:          </sources>
  22:          <switches>
  23:              <add name="DefaultSwitch" value="Information" />
  24:          </switches>
  25:          <sharedListeners>
  26:              <add name="FileLog"
  27:                   type="Microsoft.VisualBasic.Logging.FileLogTraceListener, Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"
  28:                   initializeData="FileLogWriter"/>
  29:              <!-- Uncomment the below section and replace APPLICATION_NAME with the name of your application to write to the Application Event Log -->
  30:              <!--<add name="EventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="APPLICATION_NAME"/> -->
  31:          </sharedListeners>
  32:      </system.diagnostics>
  33:      <applicationSettings>
  34:          <Xping.My.MySettings>
  35:              <setting name="WriteCMD" serializeAs="String">
  36:                  <value>INSERT [Xping]([IP],[Status],[Time],[TTL],[RTT],[Message])VALUES (@IP, @Status, GETDATE(), @TTL, @RTT, @Message)</value>
  37:              </setting>
  38:          </Xping.My.MySettings>
  39:      </applicationSettings>
  40:  </configuration>

Ну и конечно, вы должны создать таблу в базе:


   1:  CREATE TABLE [dbo].[Xping](
   2:      [i] [int] IDENTITY(1,1) NOT NULL,
   3:      [IP] [nvarchar](50) NULL,
   4:      [Status] [int] NULL,
   5:      [Time] [datetime] NULL,
   6:      [TTL] [int] NULL,
   7:      [RTT] [int] NULL,
   8:      [Message] [nvarchar](max) NULL,
   9:   CONSTRAINT [PK_Ping] PRIMARY KEY CLUSTERED 
  10:  (
  11:      [i] ASC
  12:  )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
  13:  ) ON [PRIMARY]
  14:   
  15:  GO

Вот собственно и все. Xping вы можете сгрузить в бинарном виде. Пишите пожалуйста свои замечания в баг-трекер программы.

Комментарии к этой страничке ( )
ссылка на эту страничку: http://www.vb-net.ru/Xping/index.htm
<На главную>  <В раздел ASP>  <В раздел NET>  <В раздел SQL>  <В раздел Разное>  <Написать автору>  < Поблагодарить>