![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
TIdUDPserver
DesWind © (2006-08-17 14:30:00)Есть 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 17:08:00) [1]> [32] Slym © (17.08.06 16:56)
см. моё [29]. "да и то -- при условии, что операнды не меняются".
кажется, мы
а) загадили ветку оффтопиком
б) говорим об одном и том же, но разными словами
предлагаю с оффтопом закруглиться. %-)
DesWind (2006-08-17 17:06:00) [2]Фих, там.... Не-а не влияет.... буду сравнивать.
DesWind (2006-08-17 17:01:00) [3]Хм....
> Slym © (17.08.06 16:47) [30]
Знаешь в чем разница? Я использовал DataModule для размещения компонента... Создал динамически и все заработало.... Спасибо!
Slym (2006-08-17 16:56:00) [4]или
s:=IntToStr(Random(MaxInt));
write(s[1]);
p:=pchar(s);
sleep(0);
pbytearray(p)[1];
жесткая привязка к выделенной памяти p:=pchar(s);
другой поток изменил строку, реалокнул память и асталявиста p - невалидный указатель :(
в строках потокозащищен только подсчет ссылок (PStrRec^.RefCount)! память выделяемая под содержимое строки не защищена...
Slym (2006-08-17 16:49:00) [5]Ketmar © (17.08.06 16:39) [29]
неоткуда ему взяться.
оттуда. что пока ты sleep другой поток тебе длинну строки изменил а ты по индексу букву достаешь, а длинна меньше стала :(
Slym (2006-08-17 16:47:00) [6]
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.
Ketmar (2006-08-17 16:39:00) [7]> [22] Slym © (17.08.06 16:05)
собственно, а кто сказал, что IntToStr() и StrToInt() -- потокобезопасные? потокобезопасные, афаир, только атомарные операции типа "+". да и то -- при условии, что операнды не меняются.
а AV быть не должно. неоткуда ему взяться.
DesWind (2006-08-17 16:32:00) [8]Честно!!!!! Кода больше нет!!! ))) Это просто модель.
Slym (2006-08-17 16:30:00) [9]ThreadedEvent влияет только на безопасность/стабильность работы
если ты в OnUDPRead при ThreadedEvent=true начнешь к форме приставать, то возможен Эксепшн, ThreadedEvent=false вызовет Synchronize тем самым защитит от многопоточного доступа к форме
DesWind (2006-08-17 16:30:00) [10]Ну забыл 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:23:00) [11]повторюсь:
ошибка гдето в остальном коде...
ибо твои
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:19:00) [12]Отправляю с интервалом в 1 с, попеременно символ "А" и "В". Хочу на сервере в отдельном потоке получать эти символы в той последовательности в которой оправил обрабатывать и передавать обработанные данные следующему потоку. Впринципе все это можно сделать поставив свойство ThreadedEvent в true. Тогда событие OnUDPRead будет вызываться в отдельном потоке и в этом же событии полученую строку и обрабатывать. Но меня всежтаки беспокоит, что не получилось нормально принять данные по принципу описаному в вопросе.
Slym (2006-08-17 16:08:00) [13]DesWind © (17.08.06 16:02) [21]
Вообще что хочется тебе получить? если получаешь не то то с каким эталоном сравнивать?
Slym (2006-08-17 16:05:00) [14]должен быть именно AV... может у тебя i<maxint быстро сработало... оттуда WaitFor уже убитого потока
DesWind (2006-08-17 16:02:00) [15]
> Если нарушен порядок символов так это от того что порядок
> пакетов UDP не гарантирует
А разве буфер не очищается послевыборки пакета? ведь как говорил - я гарантированно успеваю выбирать пакет до прихода следующего.
Ketmar (2006-08-17 16:00:00) [16]> [18] Slym © (17.08.06 15:54)
анализировать, что за ошибка -- лень. потому просто поверю на слово пока. %-)
зыж читал исхордник system.pas. а по-моему, она всё-таки вертится. не зря же они там InterlockedXXX() используют? глубоко анализировать лень. но есть подозрение, что задумывались именно как потокобезопасные.
Ketmar (2006-08-17 15:59:00) [17]> [18] Slym © (17.08.06 15:54)
не AV, а Thread Error: Неверный дескриптор (6). сразу. %-)
Slym (2006-08-17 15:54:00) [18]Через сколько секунд AV получил?
Slym (2006-08-17 15:53:00) [19]более наглядный пример: (поиграй {$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.
Ketmar (2006-08-17 15:53:00) [20]> [13] Slym © (17.08.06 15:36)
убедил.