Ребят вы бы азы хоть немного подучили)))
Нигде ничего не склеивается в какие-то пакеты "побольше".
TCP/IP - это потоковый протокол. Все данные передаются тупо в едином потоке.
Ну а как сказал sko, уже для разделения пакетов на программном уровне, перед началом передаваемой структуры пишется ее размер.
И да, сразу совет. Не считывайте все данные из сокета, как те только туда пришли, т.к. может быть ситуация, что пришла только часть пакета.
Поэтому логика правильного разбора пакетов должна быть такая:
считывается размер пакета из потока. Далее проверяется сколько байт доступно в потоке. Если байт не достаточно, то необходимо ждать, пока придет остальная часть. Далее считывается столько байт, какой размер указан вначале, а опять же не все данные из сокета. Ну и т.д. повторяется...
ребят, выручите плиз, скиньте функции дешифровки РСА ключа (дескрамбл), и саму функцию РСА шифрования, плиз. И вообще нужно ли на интерлюде делать дескрамбл рса ключа из пакета инит, или используем инитовский ключ как есть? в исходниках сервера вроде нету ничего связанного с кодированием рсашки
Вообще проблемка с РСА, у меня иногда рса ключ имеет отрицательное значение (если перевести его в бигинтегер), и из-за этого вылетает ошибка:
java.lang.ArithmeticException: BigInteger: modulus not positive
а если ошибка не вылетает (т.е. рса положительный), то в консоли логин сервера пишет такое:
Created new account : я┐╜p--"#я┐╜╤Зя┐╜▐Юя┐╜ on IP : 127.0.0.1
Я не могу понять, это проблема в РСА, в дескрамбле, или потому что кодировку неправильную выбрал для логина и пароля... и как исправить ошибку modulus not positive
type TPacket: packed record
case boolean of
true: (buf: array[0..8191] of byte;);
false: (len:word;
typepack:byte;);
end;
var
Packet:TPacket;
...
begin
while true do
begin
if recv(FSocket,Packet,2,MSG_PEEK)<2 then Exit;
if recv(FSocket,Packet,Packet.len,MSG_PEEK)<packet.len then Exit;
recv(FSocket,Packet,Packet.len,0);
Obrabotka(Packet); // функция обработки пакета
end;
end;
переписать приблизительно так (ну это мой вариант на тот момент, сейчас он уже еще доработан, но исходники не при мне):
Код:
...
private
FBuffer: packed array[0..8191] of byte;
FStartBuffer:integer;
FEndBuffer:integer;
...
procedure TMyClass.ReceivePackets;
var
s:Integer;
begin
s:=recv(FSocket,FBuffer[FEndBuffer],length(FBuffer)-FEndBuffer,0);
// тут нужно обработать возможные ошибки.
inc(FEndBuffer,s);
while true do
begin
if FEndBuffer-FStartBuffer<2 then Break;
move(FBuffer[FStartBuffer],Fpacket,2);
if FPacket.len>sizeof(FPacket) then
begin
// Тут нужно закрыть сокет, и сгенерировать исключение
// так как прием таких пакетов не планируется
Exit;
end;
if FEndBuffer-FStartBuffer<Fpacket.len then Break;
move(FBuffer[FStartBuffer],FPacket,Fpacket.len);
inc(FstartBuffer,Fpacket.len); // увеличиваем значение стартовой позиции буфера на величину забранных данных
if FGame then ProcessingGame else ProcessingAuth; // обработка выделенного пакета
end;
// Оптимизация буфера (чтобы обойтись без постоянных сдвигов буфера
// сдвигать будем только при крайней необходимости)
// Если буфер пустой, устанавливаем позиции начала и конца на 0
if FStartBuffer>=FEndBuffer then
begin
FStartBuffer:=0;
FEndBuffer:=0;
end;
// Оцениваем длину свободного хвоста буфера, если он менее 2 кб, то сдвигаем данные к началу буфера
if length(FBuffer)-FEndBuffer<2048 then
begin
move(FBuffer[FStartBuffer],FBuffer[0], FEndBuffer-FStartBuffer);
FEndBuffer:=FEndBuffer-FStartBuffer;
FStartBuffer:=0;
end;
end;
Последний раз редактировалось glukmaker, 29.02.2012 в 15:24.
ну собственная буферизация имеет смысл только в том случае если обработка данных слишком долгая, и возможно переполнение буфера сокета.
Несогласен, т.к. своя буферизация еще и избавляет от проблем связанных с приемом данных из разных фреймов. Если пришел не полный пакет, отпадает необходимость ожидания дочитывания остатка, а такое по моему опыту бывает часто, когда прилетает нецелое количество пакетов. Можно спокойно отпустить сокет для приема дальше, и заняться обработкой имеющихся полных пакетов. Ассинхронное использование сокета короче.
Последний раз редактировалось Sherman, 02.03.2012 в 14:28.
Demion, проблема в том, что этот код пробовал использовать, я ему скармливаю свой рса ключ, а в ответ он отдаёт его же, т.е. ничего не изменив... может у меня рса не закодирован???
Добавлено через 6 минут
и проблема в том что вышибает постоянно вот эта ошибка (через раз) :
java.lang.ArithmeticException: BigInteger: modulus not positive
Я понимаю что это потому что после перевода ключа в биг интегер оно может иметь отрицательное значение и при использовании функции:
r = d.modPow(exp, m);
Оно вылетает (в переменную m записан биг интегер, полученный из РСА)
Последний раз редактировалось ErgoZ, 02.03.2012 в 14:53.
Причина: Добавлено сообщение