Вычислить контрольную сумму по модулю 256 в PHP

Я уже искал Stackoverflow и, к сожалению, ничего не нашел. Я работаю с протоколом FIX, и мне нужно сгенерировать контрольную сумму по модулю 256, как описано на http://fixwiki.fixprotocol.org/fixwiki/CheckSum.

$count = strlen($message);
$count = $count % 256;
$checksum = 256 - $count;

if(strlen($checksum) == 1) {
    $checksum = '00' . $checksum;   
}

if(strlen($checksum) == 2) {
    $checksum = '0' . $checksum;    
}

Используя строку FIX:

8=FIX.4.2|9=42|35=0|49=A|56=B|34=12|52=20100304-07:59:30

Он должен вернуться:

8=FIX.4.2|9=42|35=0|49=A|56=B|34=12|52=20100304-07:59:30|10=185|

Однако мой скрипт возвращает:

8=FIX.4.2|9=42|35=0|49=A|56=B|34=12|52=20100304-07:59:30|10=199|

Я был бы признателен, если бы кто-то мог указать мне в правильном направлении!


person Ashley    schedule 26.10.2012    source источник
comment
Проверьте этот пост stackoverflow.com/questions/2959788 /   -  person FabianoLothor    schedule 26.10.2012
comment
Я просмотрел эту ветку, но не увидел ничего конкретного в расчете, который мне нужен выше.   -  person Ashley    schedule 26.10.2012
comment
Значение $count равно 57 при использовании strlen() и mb_strlen().   -  person Ashley    schedule 26.10.2012


Ответы (2)


Согласно http://fixwiki.fixprotocol.org/fixwiki/CheckSum, контрольная сумма не просто длина сообщения по модулю 256.
Это сумма каждого символа (как значение ascii) по модулю 256.

<?php
define('SOH', chr(0x01));

$message = '8=FIX.4.2|9=42|35=0|49=A|56=B|34=12|52=20100304-07:59:30|';
$message = str_replace('|', SOH, $message);
echo $message, GenerateCheckSum($message);

function GenerateCheckSum($message) {
    $sum = array_sum(
        array_map(
            'ord', 
            str_split($message, 1)
        )
    );
    $sum %= 256;
    return sprintf('10=%03d%s', $sum, SOH);
}

отпечатки

8=FIX.4.2 9=42 35=0 49=A 56=B 34=12 52=20100304-07:59:30 10=185

или чтобы оставаться ближе к примеру функции в документации

<?php
define('SOH', chr(0x01));

$message = '8=FIX.4.2|9=42|35=0|49=A|56=B|34=12|52=20100304-07:59:30|';
$message = str_replace('|', SOH, $message);
echo $message, '10=', GenerateCheckSum($message, strlen($message)), SOH;

function GenerateCheckSum($buf, $bufLen )
{
   for( $idx=0, $cks=0; $idx < $bufLen; $cks += ord($buf[ $idx++ ]) );
   return sprintf( "%03d", $cks % 256);
}
person VolkerK    schedule 26.10.2012
comment
Спасибо тебе за это! Работает удовольствие! - person Ashley; 29.10.2012

Возможно, ваша строка содержит несколько байтовых символов. Попробуйте mb_strlen.

person Explosion Pills    schedule 26.10.2012
comment
Я повторил как strlen(), так и mb_strlen(), и оба возвращают 56 для приведенного выше примера. - person Ashley; 26.10.2012
comment
На самом деле это 57, я пропустил вертикальную черту при копировании примера. - person Ashley; 26.10.2012