У меня не получается правильно установить связь с клиентом (при неправильном ответе сервера браузер разрывает соединение).
Браузеры которые уже поддерживают эту технологию - Google Chrome (текущая стабильная версия), Opera 10.70 (альфа). Тестирую на Хроме.
Вот пару ссылок на русском с описанием генерации ключей:
http://www.websockets.ru/node/8
http://ru.wikipedia.org/wiki/WebSocket
Алгоритм:
...16-байтное тело ответа, вычисляемое следующим образом:
- 1. из строки со значением заголовка запроса Sec-WebSocket-Key1 исключить все символы, не являющиеся цифрами (не попадающие в диапазон '0'..'9');
2. полученную строку превратить в 64-битное целое число (для примера выше получим 1299853100);
3. полученное число разделить целочисленным делением на количество пробелов в исходной строке со значением заголовка;
4. полученное число представить в виде 4-х байтового 32-битного числа в формате big endian: старший байт хранится по нулевому смещению;
5. проделать то же самое с заголовком Sec-WebSocket-Key2;
6. интерпретируя числа из пунктов 4) и 5) как 4-х байтовые строки, конкатенировать их (сложить в одну строку) и добавить как строку тело запроса (это последние 8 байт);
7. вычислить от полученной 16-байтной строки значение MD5 и записать это значение в тело ответа "как есть", без преобразования в какое-либо представление;
Вот ключевые (спорные) фрагменты программы:
- Код: Выделить всё
function int32_s(a: integer): string;
//Ф-я конвертирующая 32 битное число в строку (Big Endian сохраняется)
var i: integer;
begin
result := '';
for i := 3 downto 0 do begin
Result += chr((a shr i*8)and $ff);
end;
end;
var ...
data: array[1..1024] of byte; //полученные от клиента байты
size: integer; //размер запроса от клиента
k1,k2,k3: string;
sp1, sp2: integer; //пробелы в первом и втором ключах
key32_1, key32_2: cardinal; //ключи (число / пробелы)
b: array[0..15] of Byte; //буфер для md5
...
begin
...
//последние 8 байт это KEY3 (представляем байты в виде строки)
k3 := Chr(data[size-7])+Chr(data[size-6])+Chr(data[size-5])+Chr(data[size-4])
+Chr(data[size-3])+Chr(data[size-2])+Chr(data[size-1])+Chr(data[size]);
{
По пунктам 1-5 - УВЕРЕН все сделано правильно - выбрал из строк числа, поделил на пробелы (числа всегда кратные кол-ву пробелов) - так и должно быть
}
//делим полученные числа на пробелы (3 пункт)
key32_1 := StrToInt64(key1) div sp1;
key32_2 := StrToInt64(key2) div sp2;
//соединяем ключи (6 ПУНКТ)
result_key:= int32_s(key32_1) + int32_s(key32_2) + k3;
//MD5 (7 ПУНКТ)
b := MD5String(result_key);
result_key := '';
for i := 0 to 15 do result_key += chr(b[i]);
//Правильно ли я посчитал эту самую РЕЗУЛЬТИРУЮЩУЮ строку??? нет ли ошибок в коде?
end;
Вобщем, когда вконце ответа выдаю эту строку - клиент разрывает соединение.
Подскажите пожалуйста - может неправильно преоразования от байт к строкам делал? или c md5 не так чтото вызвал?
Собственно подвопросы - верная ли функция int32_s и правильно ли представил хэш md5 в виде строки "как есть"?
Добавлено спустя 7 часов 30 минут 44 секунды:
Нашел ошибку...
- Код: Выделить всё
Result += chr((a shr i*8)and $ff);
а надо так
- Код: Выделить всё
Result += chr((a shr (i*8))and $ff);
Побитовые операции имеют более высокий приоритет
