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

Вниз

Сокеты "склеивают" сообщения!   Найти похожие ветки 

 
Galiaf   (2005-09-20 20:31) [0]

Драсти. Проблема такая: если очень быстро послать сокетом текст "привет" то придёт он в таком виде "приветпривет" :(.
Не катит!
Помогите с проблемой разобраться, как отправлять что бы не склеивало, потому что отправлять придётся много и быстро, это будет использоваться в сетевой игре и отсылать буду очень важные данные.


 
KLAUS ©   (2005-09-20 20:47) [1]

А ты как вообще отправляешь?

procedure TForm1.Button1Click(Sender: TObject);
 begin

   ClientSocket1.Socket.SendText(Edit1.Text);
      Edit13.Text := "";
   ActiveControl := Edit13;
end;


 
Galiaf   (2005-09-20 21:22) [2]

Отправлял я по нажатию на Enter но без строки "ActiveControl := Edit13;", а что она делает?


 
kami ©   (2005-09-20 21:29) [3]


> что бы не склеивало

1.Посылать перед каждым текстом его длину [ другую служебную информацию ]
2.Сохранять всё принятое в конец MemoryStream
3.Просматривать с начала MemoryStream после каждого приема, выбирая пришедшие полностью сообщения и, соответственно, удаляя их из потока.

Это защитит не только от склеивания, но и от разбиения по пакетам.


 
XProger ©   (2005-09-20 22:01) [4]

http://xproger.mirgames.ru/files/lib/l_net.rar

Библиотека готового сетевого протокола основанного на UDP. Имеется реализация гарантированной доставки пакетов, а также широковещательные рассылки. Прилагается пример чата. Прирост к исполняемому файлу составляет 5.5 кб!


 
Galiaf   (2005-09-20 22:06) [5]

kami ©   (20.09.05 21:29) [3]
Всё это звучит весьма достойно но страшно, я не очень разбираюсь в сетевых вопросах прошу доступный для понимания пример(желательно с пояснениями), спасибо.


 
Delphi_is_cool ©   (2005-09-21 00:53) [6]

Ставь между сообщениями пробел ? )


 
kami ©   (2005-09-21 01:04) [7]

> но страшно

А чего тут страшного ? Сам пару месяцев назад так думал.

Пример...
Предполагаю, что соединение ClientSocket - ServerSocket уже установлено, отправка производится с клиента на сервер, тогда :

type
 TMyData=record
   Length:Word;// здесь будет храниться длина пересылаемой строки
   //---------- другая необходимая информация
   myText:string;
 end;
 //-----------------------------------
 MyStream:TMemoryStream;
 procedure MySendText(MyText:string);

// где создать MyStream - без понятия, например, в FormCreate, тогда уничтожить - в FormDestroy

procedure MySendText(MyText:string);
var
 MyData:TMyData;
begin
 MyData.Length:=Length(MyText);
 MyData.myText:=MyText;{в принципе,это все лишнее,если структура TMyData ограничится только этими полями}
 ClientSocket.Socket.SendBuf(MyData.Length);
 ClientSocket.Socket.SendBuf(MyData.myText[1],MyData.Length);
end;

{ пересылать вот так, непосредственно буфером тоже не совсем верно - при заполнении буфера самого сокета может не отослаться, реализация такой защиты в http://delphimaster.net/view/6-1122136315/ }

на сервере в OnClientRead:
var
 Buf:Array of byte;// временный массив, куда "запихнем" всё, что прислали с клиента
 Size:integer;// размер принятой информации
 MyData:TMyData;// сюда "складываем" принятые строки (по очереди)
 TempStream:TMemoryStream;//совсем временный поток :)
begin
 Size:=Socket.ReceiveLength;
 SetLength(Buf,Size);
 Socket.ReceiveBuf(Buf[0],Size);

 MyStream.Seek(0,soFromEnd)//добавляем данные в буфер FIFO, которым является MyStream
 MyStream.Write(Buf[0],Size);
 { теперь в MyStream содержатся все данные принятые прежде и не выбранные (по причине того, что приняты не полностью) + принятые сейчас в формате: длина строки | содержание строки}

 // начинаем выборку
 repeat
   if MyStream.Size<SizeOf(Word){ + минимальный_размер_длинной_строки } then
     break;// больше выбирать нечего, все данные закончились
   MyStream.Read(MyData.Length,SizeOf(Word));  // считали длину строки
   if (MyStream.Size-MyStream.Position)>=MyData.Length then
   { если запись, которую пытаемся выбрать, пришла полностью, то можно продолжить выборку текущей записи}
     begin
       SetLength(MyData.myText,MyData.Length);
       MyStream.Read(MyData.myText[1],MyData.Length);
       { запись считана, теперь нужно удалить ее из потока}
       { следующий код - далеко не лучшее решение, но сейчас в голову ничего не приходит}
       TempStream:=TMemoryStream.Create;
       TempStream.CopyFrom(MyStream,MyStream.Size-MyStream.Position);//скопируем все, кроме уже считанного
       MyStream.Clear;
       MyStream.LoadFromStream(TempStream);// и занесем обратно
       TempStream.Free;
       DoSomethingWithString(MyData.myText);// вместо этого - реальный обработчик пришедшей строки
     end
   else
     break;//строка, до которой дошли, пришла не полностью, будем ждать следующего пакета, чтобы дополнить недостающее
 until False;
end;


ЗЫ. Писалось по памяти, без Delphi, так что могут быть некоторые ошибки. Но общий принцип - примерно такой.


 
kami ©   (2005-09-21 01:09) [8]

Упс...
 Сразу после repeat :
MyStream.Position:=0;



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

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

Наверх





Память: 0.49 MB
Время: 0.018 c
14-1134073101
wicked
2005-12-08 23:18
2006.01.01
предложение по улучшению форума...


2-1134576874
Змей
2005-12-14 19:14
2006.01.01
отлавливание sc_minimize


2-1134678303
Змей
2005-12-15 23:25
2006.01.01
Вырезка слова из строки


14-1134211666
Shastox
2005-12-10 13:47
2006.01.01
Подтасовка IP


14-1133939232
GR
2005-12-07 10:07
2006.01.01
Как быть со следующим поколением?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский