Главная страница
    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.009 c
1-1133517137
Oleg_358367
2005-12-02 12:52
2006.01.01
скорость for и while


14-1134232474
x.pro
2005-12-10 19:34
2006.01.01
Доставка цветов.


2-1134645406
dapher
2005-12-15 14:16
2006.01.01
Конструкторы


14-1134235288
Kerk
2005-12-10 20:21
2006.01.01
Весь день кодю на Прологе.


3-1131603472
db_noob
2005-11-10 09:17
2006.01.01
Добавление поля в ADOTable





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