Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2004.08.08;
Скачать: [xml.tar.bz2];

Вниз

подсчет контрольных сумм   Найти похожие ветки 

 
ev   (2004-06-08 19:55) [0]

подскажите, как считаются контрольные суммы у пакетов Ethernet, IP, ICMP, TCP, UDP


 
Verg ©   (2004-06-08 21:00) [1]

Контрольная сумма.

  С контрольной суммой в сетях TCP/IP имеется некоторая путаница.
  Алгоритм ее подсчета, претендующий быть определением, изложен в
  RFC про IP. Если написать программу по этому алгоритму, она будет
  считать все, что угодно, но не ту контрольную сумму, которую
  считают Ваши соседи на сети. Есть даже отдельный RFC про контрольную
  сумму, RFC1071, но вопрос все равно остается мутным.

  На самом деле, все просто. Контрольная сумма считается следующим
  образом. Пусть есть блок из N байтов. Если N нечетное, то мы дополняем
  этот блок еще одним, нулевым, байтом. Потом мы пробегаем этот блок
  последовательно, вытаскивая из него по 16-битному слову. Каждое такое
  слово мы считаем 16-битным числом с сетевым порядком байтов, и складываем
  их в некотором 16-битном аккумуляторе. Биты, вылазящие из аккумулятора
  вверх, в переполнение, мы прибавляем к младшему разряду аккумулятора.
  Результат этого суммирования побитно инвертируется и становится, собственно,
  значением подсчитанной контрольной суммы.

  Такая контрольная сумма обладает некоторыми забавными свойствами.

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

  Вот переносимая функция, которая считает контрольную сумму:

       ushort  net_checksum( void *data, size_t len )
       {
           ulong       sum = 0;
           ushort      *dp = data;
           ushort      sum_s;
           int         words = len >> 1;

           while( words -- )
               sum += *dp ++;

           if( len & 1 )
               sum += *(uchar*) dp;

           sum = (ushort) sum + (sum >> 16) & 0xffff;
           sum_s = (ushort) sum + (ushort)(sum >> 16);
           return sum_s != 0xffff ? ~sum_s : sum_s;
       }

  Второе. Контрольная сумма непустого блока никогда не равна нулю.

  Третье. Если мы возьмем блок данных, в котором отведено место под
  контрольную сумму:

       struct { ushort sum; opaque data; } my_data;

  Потом обчексуммим этот блок:

       my_data.sum = 0;
       my_data.sum = net_checksum( &my_data, sizeof( my_data ) );

  То контрольная сумма блока с уже положенной в него контрольной суммой
  будет всегда равна 0xffff:

      if( net_checksum( &my_data, sizeof( my_data ) ) != 0xffff )
          printf( "CRC error!\n" );

  Четвертое. Контрольные суммы можно складывать, не забывая добавлять
  переносы к младшему биту. Это дает то же самое, как если бы из двух
  блоков составить один длинный, и подсчитать контрольную сумму от него.
  По очевидным причинам блок, который идет первым, должен иметь четную
  длину. У такого сложения есть одна паталогия: если контрольные суммы
  двух половинок взаимно комплементарны, то после сложения получится 0,
  а после подсчета суммы от суммарного блока получилось бы 0xffff.
  Это надо учитывать:

       ushort  net_chksum_add( ushort s1, ushort s2 )
       {
           ulong       sum = (ulong) s1 + (ulong) s2;
           ushort      usum = (ushort) sum;

           sum = sum > 0xffff ? usum + 1 : usum;
           if( !sum && (s1 || s2) )
               return 0xffff;
           else
               return sum;
       }

  Кстати, число 0xffff для контрольной суммы играет роль нуля: оно получается
  при чексуммировании блока из одних нулей, и прибавление этого числа к
  контрольной сумме ее не меняет.

  И теперь, как этим пользоваться.

  Перед отправкой пакета мы говорим:

       ip -> ip_sum = 0;
       ip -> ip_sum = net_checksum( ip, sizeof( ip_header ) );

  При приеме мы проверяем:

       if( net_checksum( ip, ip_hdr_size ) != 0xffff )
           error( "Invalid checksum!" );

Copyright (c) by Alexander Pevzner (pzz@pzz.msk.ru), 1998-1999


 
ev   (2004-06-08 21:17) [2]

большое спасибо :)

пойду реализовывать для микроконтроллера....



Страницы: 1 вся ветка

Форум: "Сети";
Текущий архив: 2004.08.08;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.47 MB
Время: 0.033 c
1-1090680966
Dima_Delphi
2004-07-24 18:56
2004.08.08
Как очистить Stringgrid


8-1085146010
tse
2004-05-21 17:26
2004.08.08
mp3


1-1090902631
race1
2004-07-27 08:30
2004.08.08
смещение


14-1090674344
AlexG
2004-07-24 17:05
2004.08.08
Что такое ДЕЛЕГАТЫ?


3-1089723069
STM
2004-07-13 16:51
2004.08.08
Pack dbf из Delphi





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский