Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.01.14;
Скачать: CL | DM;

Вниз

TIdUDPserver   Найти похожие ветки 

 
DesWind ©   (2006-08-17 14:30) [0]

Есть UDP-клиент, который отправляет данные таким образом

procedure SomeEvent(Sender: TObject);
var
str: string

begin

....
udpClient.Send(str);

end;

Настроен на конкретный IP.

Есть UDP сервер, настроенный(может не правильно) принимать пакеты с любого IP.


procedure TSomeThread.Execute;
var
Str: string;

begin
 Str:=dtmRecive.udpRecive.ReceiveString();
 CritSec.Acquire;
  try
   DataStrs:=DataStrs+Str;
  finally
   CritSec.Release;
  end;
end;


Так вот строки приходят через одну, т.е если посылать то "А" то "В" - приходят только "В". Что я делаю не так?


 
Ketmar ©   (2006-08-17 14:37) [1]

а зачем критическая секция? для строк не надо. %-)


 
DesWind ©   (2006-08-17 14:45) [2]

Ниче здоровее будет.


 
Ketmar ©   (2006-08-17 14:54) [3]

а вообще -- для udp нет буфера. если ты не успел забрать пакет до прихода нового -- то уже и не заберёшь никогда. есть подозрение, что пакеты приходят шутсро, а забираются медленно. потому и теряются -- старый пакет перезаписывается новым до выборки.


 
Slym ©   (2006-08-17 14:57) [4]

DesWind ©   (17.08.06 14:30)
если посылать то "А" то "В" - приходят только "В".

Файрвол на букву "А" :)


 
DesWind ©   (2006-08-17 15:01) [5]

Вообще-то оправляется по одному символу где-то раз в 10 сек. Выбирать я их точно успеваю.


 
DesWind ©   (2006-08-17 15:18) [6]

А вообще получаются очень интересные строчики на выходе типа такого "ABBBBBBBABBBBBBABBBBBBABBBBBBABBBBBBABBBBBBABBBBBBABBBBBBA", или еще какойнить рисунок.... Ниче не понимаю!!!!


 
Slym ©   (2006-08-17 15:22) [7]

Ketmar ©   (17.08.06 14:37) [1]
а зачем критическая секция? для строк не надо

Надо... строка это сложный поточно незащищенный ресурс
DesWind ©   (17.08.06 15:01) [5]
Выбирать я их точно успеваю

ошибка гдето в остальном коде...


 
Ketmar ©   (2006-08-17 15:23) [8]

так может пакеты вообще теряются нафиг в дороге. "была зима, на небе были тучи..." (ц)
по твоему коду нифига не ясно.


 
Slym ©   (2006-08-17 15:23) [9]

DesWind ©   (17.08.06 15:18) [6]
Если нарушен порядок символов так это от того что порядок пакетов UDP не гарантирует


 
Ketmar ©   (2006-08-17 15:24) [10]

> [7] Slym ©   (17.08.06 15:22)
> строка это сложный поточно незащищенный ресурс
точно? я полез читать исходник. потому как мне память подсказывает, что это не совсем правда.


 
Slym ©   (2006-08-17 15:26) [11]

Ketmar ©   (17.08.06 14:54) [3]
для udp нет буфера

откуда это? по дефолту буфер есть у всех... в т.ч. и у RAW соков только буфер то маленький... и все что в него не влазит - игнорится (UDP)


 
Ketmar ©   (2006-08-17 15:27) [12]

> [11] Slym ©   (17.08.06 15:26)
я имел в виду "такого, как для TCP, где накапливаются пакеты". накопления не происходит, новоприбывший пакет замещает старый.


 
Slym ©   (2006-08-17 15:36) [13]

Ketmar ©   (17.08.06 15:24) [10]
что это не совсем правда

попробуй:
program Project2;

{$APPTYPE CONSOLE}

uses
 SysUtils,Classes;

type
 TTestThread=class(TThread)
 protected
   procedure Execute; override;
 end;

var s:string;
var t:TTestThread;

procedure TTestThread.Execute;
var i:integer;
begin
 FreeOnTerminate:=true;
 repeat
   i:=StrToInt(s);
   sleep(0);
   if i<>StrToInt(s) then raise exception.Create("Alarm");
   s:=IntToStr(i+1);
   writeln(s);
 until not(i<maxint);
end;

begin
 s:="0";
 TTestThread.Create(false);
 t:=TTestThread.Create(false);
 t.WaitFor;
end.


 
DesWind ©   (2006-08-17 15:37) [14]


> ошибка гдето в остальном коде...

Остального кода нет :), разве что по таймеру в мемо выводится DataStrs. Если перевести TidUDPServer на события (т.е. выбирать данные по событию IdUDPServer1UDPRead), то все приходит нормально как и должно, но меня события не устраивают.


 
Slym ©   (2006-08-17 15:39) [15]

Slym ©   (17.08.06 15:36) [13]
а теперь так:
program Project2;

{$APPTYPE CONSOLE}

uses
 SysUtils,Classes,SyncObjs;

type
 TTestThread=class(TThread)
 protected
   procedure Execute; override;
 end;

var s:string;
var cs:TCriticalSection;
var t:TTestThread;

procedure TTestThread.Execute;
var i:integer;
begin
 FreeOnTerminate:=true;
 repeat
   cs.Enter;
   try
     i:=StrToInt(s);
     sleep(0);
     if i<>StrToInt(s) then raise exception.Create("Alarm");
     s:=IntToStr(i+1);
     writeln(s);
   finally
     cs.Leave;
   end;
 until not(i<maxint);
end;

begin
 s:="0";
 cs:=TCriticalSection.Create;
 try
   TTestThread.Create(false);
   t:=TTestThread.Create(false);
   t.WaitFor;
 finally
   cs.Free;
 end;
end.


 
Ketmar ©   (2006-08-17 15:53) [16]

> [13] Slym ©   (17.08.06 15:36)
убедил.


 
Slym ©   (2006-08-17 15:53) [17]

более наглядный пример: (поиграй {$define threadsafe})
program Project2;

{$APPTYPE CONSOLE}
//{$define threadsafe}

uses
 SysUtils,Classes,SyncObjs;

type
 TTestThread=class(TThread)
 protected
   procedure Execute; override;
 end;

var s:string;
var t:TTestThread;
{$ifdef threadsafe}
var cs:TCriticalSection;
{$endif}

procedure TTestThread.Execute;
var i:integer;
begin
 FreeOnTerminate:=true;
 repeat
   {$ifdef threadsafe}
   cs.Enter;
   try
   {$endif}
     s:=IntToStr(Random(MaxInt));
     s:=s+s+s+s+s+s+s+s+s+s+s+s;//усилим эффект
     i:=length(s);
     sleep(0);
     write(s[i]);
   {$ifdef threadsafe}
   finally
     cs.Leave;
   end;
   {$endif}
 until not(i<maxint);
end;

begin
 {$ifdef threadsafe}
 cs:=TCriticalSection.Create;
 try
 {$endif}
   TTestThread.Create(false);
   t:=TTestThread.Create(false);
   t.WaitFor;
 {$ifdef threadsafe}
 finally
   cs.Free;
 end;
 {$endif}
end.


 
Slym ©   (2006-08-17 15:54) [18]

Через сколько секунд AV получил?


 
Ketmar ©   (2006-08-17 15:59) [19]

> [18] Slym ©   (17.08.06 15:54)
не AV, а Thread Error: Неверный дескриптор (6). сразу. %-)


 
Ketmar ©   (2006-08-17 16:00) [20]

> [18] Slym ©   (17.08.06 15:54)
анализировать, что за ошибка -- лень. потому просто поверю на слово пока. %-)

зыж читал исхордник system.pas. а по-моему, она всё-таки вертится. не зря же они там InterlockedXXX() используют? глубоко анализировать лень. но есть подозрение, что задумывались именно как потокобезопасные.


 
DesWind ©   (2006-08-17 16:02) [21]


> Если нарушен порядок символов так это от того что порядок
> пакетов UDP не гарантирует


А разве буфер не очищается послевыборки пакета? ведь как говорил - я гарантированно успеваю выбирать пакет до прихода следующего.


 
Slym ©   (2006-08-17 16:05) [22]

должен быть именно AV... может у тебя i<maxint быстро сработало... оттуда WaitFor уже убитого потока


 
Slym ©   (2006-08-17 16:08) [23]

DesWind ©   (17.08.06 16:02) [21]
Вообще что хочется тебе получить? если получаешь не то то с каким эталоном сравнивать?


 
DesWind ©   (2006-08-17 16:19) [24]

Отправляю с интервалом в 1 с, попеременно символ "А" и "В". Хочу на сервере в отдельном потоке получать эти символы в той последовательности в которой оправил обрабатывать и передавать обработанные данные следующему потоку. Впринципе все это можно сделать поставив свойство ThreadedEvent в true. Тогда событие OnUDPRead будет вызываться в отдельном потоке и в этом же  событии полученую строку и обрабатывать. Но меня всежтаки беспокоит, что не получилось нормально принять данные по принципу описаному в вопросе.


 
Slym ©   (2006-08-17 16:23) [25]

повторюсь:
ошибка гдето в остальном коде...
ибо твои
procedure TSomeThread.Execute;
var Str: string;
begin
Str:=dtmRecive.udpRecive.ReceiveString();
CritSec.Acquire;
 try
  DataStrs:=DataStrs+Str;
 finally
  CritSec.Release;
 end;
end;

не код потока :(


 
DesWind ©   (2006-08-17 16:30) [26]

Ну забыл while скопировать )))

while not Terminated do
 begin
  str:=dtmRecive.udpRecive.ReceiveString;
  CritSec.Acquire;
  try
   DataStrs:=DataStrs+Str;
  finally
  CritSec.Release;
  end;
 end;

и есть еще в основном модуле

procedure TfmMain.FormCreate(Sender: TObject);
begin
RecThrd:=TReciveTread.Create(false);
tmrRecive.Enabled:=true;
end;

procedure TfmMain.FormDestroy(Sender: TObject);
begin
tmrRecive.Enabled:=false;
RecThrd.Terminate;
RecThrd.WaitFor;
RecThrd.Free;
end;

procedure TfmMain.tmrReciveTimer(Sender: TObject);
begin
CritSec.Acquire;
memData.Text:=DataStrs;
CritSec.Release;
end;


 
Slym ©   (2006-08-17 16:30) [27]

ThreadedEvent влияет только на безопасность/стабильность работы
если ты в OnUDPRead при ThreadedEvent=true начнешь к форме приставать, то возможен Эксепшн, ThreadedEvent=false вызовет Synchronize тем самым защитит от многопоточного доступа к форме


 
DesWind ©   (2006-08-17 16:32) [28]

Честно!!!!! Кода больше нет!!! ))) Это просто модель.


 
Ketmar ©   (2006-08-17 16:39) [29]

> [22] Slym ©   (17.08.06 16:05)
собственно, а кто сказал, что IntToStr() и StrToInt() -- потокобезопасные? потокобезопасные, афаир, только атомарные операции типа "+". да и то -- при условии, что операнды не меняются.
а AV быть не должно. неоткуда ему взяться.


 
Slym ©   (2006-08-17 16:47) [30]

program Project1;

{$APPTYPE CONSOLE}

uses
 SysUtils,
 Classes,
 SyncObjs,IDUDPServer;

type
 TTestThread=class(TThread)
 protected
   procedure Execute; override;
 end;
var Sock:tIDUdpServer;
var s:string;
var t:TTestThread;
var cs:TCriticalSection;
var i:integer;

procedure TTestThread.Execute;
var str:string;
begin
 FreeOnTerminate:=true;
 repeat
   str:=Sock.ReceiveString;
   cs.Enter;
   try
     s:=s+str;
   finally
     cs.Leave;
   end;
 until terminated;
end;

begin
 cs:=TCriticalSection.Create;
 try
   Sock:=tIDUdpServer.Create;
   try
     Sock.DefaultPort:=3052;
     Sock.Active:=true;
     t:=TTestThread.Create(false);
     for i:=0 to 255 do
     begin
       sleep(1000);
       cs.Enter;
       try
         Writeln(s)
       finally
         cs.Leave
       end;
     end;
     t.Terminate;
   finally
     Sock.Free;
   end;
 finally
   cs.Free;
 end;
end.


 
Slym ©   (2006-08-17 16:49) [31]

Ketmar ©   (17.08.06 16:39) [29]
неоткуда ему взяться.

оттуда. что пока ты sleep другой поток тебе длинну строки изменил а ты по индексу букву достаешь, а длинна меньше стала :(


 
Slym ©   (2006-08-17 16:56) [32]

или
s:=IntToStr(Random(MaxInt));
write(s[1]);
p:=pchar(s);
sleep(0);
pbytearray(p)[1];


жесткая привязка к выделенной памяти p:=pchar(s);
другой поток изменил строку, реалокнул память и асталявиста p - невалидный указатель :(
в строках потокозащищен только подсчет ссылок (PStrRec^.RefCount)! память выделяемая под содержимое строки не защищена...


 
DesWind ©   (2006-08-17 17:01) [33]

Хм....

> Slym ©   (17.08.06 16:47) [30]

Знаешь в чем разница? Я использовал DataModule для размещения компонента... Создал динамически и все заработало.... Спасибо!


 
DesWind ©   (2006-08-17 17:06) [34]

Фих, там.... Не-а не влияет.... буду сравнивать.


 
Ketmar ©   (2006-08-17 17:08) [35]

> [32] Slym ©   (17.08.06 16:56)
см. моё [29]. "да и то -- при условии, что операнды не меняются".
кажется, мы
а) загадили ветку оффтопиком
б) говорим об одном и том же, но разными словами
предлагаю с оффтопом закруглиться. %-)



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

Текущий архив: 2007.01.14;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.046 c
1-1164097566
infom
2006-11-21 11:26
2007.01.14
Переназначение обработчиков событий у компонентов.


2-1167114623
wooow1
2006-12-26 09:30
2007.01.14
string &amp;&amp; array of Char


15-1166630309
vidiv
2006-12-20 18:58
2007.01.14
борьба со спамом. идея 2.


6-1155730369
Antonydee
2006-08-16 16:12
2007.01.14
Помогите разобраться


15-1166473242
Petr V. Abramov
2006-12-18 23:20
2007.01.14
Маразм крепчает. Да здравствует совок...