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

Вниз

Дополнительный поток и Exception в главном. Что будет?   Найти похожие ветки 

 
Германн ©   (2006-10-16 01:31) [80]


> Kolan ©   (16.10.06 01:06) [70]
>
>
> > Возможно даже, что у тебя никогда проблемм и не будет,
>  а
> > будут они у пользователей!
> >
>
> А какие. Пусть у меня перед сном вообще моск прокиснет и
> я как Гоголь возьму и сотру эти модули, которые писал и
> доробатывал 1,5 года :)
>

Ну вот давеча наблюдали всем техотделом такую ситуацию. В программе, где идёт работа с портом возникло исключение. Программа сдохла, но перезапустить её не было никакой возможности. Даже на CAD система не реагировала! :-)


 
Kolan ©   (2006-10-16 01:34) [81]


> Не совсем. Т.е., Resume должен делать первичный поток.

Даааа... а в справке тока: Pauses a running thread.
У меня поток сам себя усыпляет:

 while not Terminated do
 begin
   if ReadIndex >= WriteIndex then
   begin
     Suspend;
//****


> Если это еще и Ex - то и, например, по получению QueueUserAPC.


QueueUserAPC Да, это я еще...

Я понял что вместо Suspend надо сделать
 WaitForSingleObject(Event, INFINITE);  - не так? Нужен именно Ex? - С этой ф-цие не работал...  :(


 
Kolan ©   (2006-10-16 01:37) [82]


> В программе, где идёт работа с портом возникло исключение.

До сегодняшнего дня у меня небыло исключений. в окрестности порта. Ошибочки обрабатывал с пом. Enumeration.. Вот решил за исключения взяться.

А работа с портом в потоке - это из нета. А как еще чтобы не висло?


 
Leonid Troyanovsky ©   (2006-10-16 01:41) [83]


> Kolan ©   (16.10.06 01:34) [81]

> У меня поток сам себя усыпляет:


Усыпиться-то он может. А вот resume нужен извне.

>  WaitForSingleObject(Event, INFINITE);  - не так? Нужен
> именно Ex? - С этой ф-цие не работал...  :(

Ну, у молодых все еще спереди :)
Вкл., возможно, ReadFileEx & etc.

--
Regards, LVT.


 
Kolan ©   (2006-10-16 01:41) [84]

Да вот сюда я и попадаю со своим исключением.

{$IFDEF LINUX}
 if Thread.FSuspended then sem_wait(Thread.FCreateSuspendedSem);
{$ENDIF}
 try
   if not Thread.Terminated then
   try
     Thread.Execute;
   except
     Thread.FFatalException := AcquireExceptionObject;
   end;

Отсюда и неверный дискриптор...


 
Kolan ©   (2006-10-16 01:53) [85]


> А вот resume нужен извне.

Да это извне ессно.
При добавлении новых данных делается Resume. Все же тут разницы нет наверно. Что Resume что SetEvent...


> Ex

Надо посмотреть


> Да вот сюда я и попадаю со своим исключением.

Ни че не пойму с этими исключениями...
Если:
try
   SeparateHeaderAndUserDtaArrays(Package, Header, UserData);
 except
   Result.Free;
   //raise;
 end;

Это же исключение обработано? Так?
Так че оно в
except
    Thread.FFatalException := AcquireExceptionObject;

поподает?


 
Германн ©   (2006-10-16 01:59) [86]


> Kolan ©   (16.10.06 01:37) [82]
>
>
> > В программе, где идёт работа с портом возникло исключение.
>
>
> До сегодняшнего дня у меня небыло исключений. в окрестности
> порта. Ошибочки обрабатывал с пом. Enumeration.. Вот решил
> за исключения взяться.
>
> А работа с портом в потоке - это из нета. А как еще чтобы
> не висло?
>

Дык, исторически микросхема UART представляла максимум возможностей для асинхронной работы с ней. Драйверы СОМ-порта в Windows умеют использовать эти возможности.
Ну а в Дельфи оьрати внимание на параметр FILE_FLAG_OVERLAPPED и на


 
Kolan ©   (2006-10-16 08:30) [87]


> Ну а в Дельфи оьрати внимание на параметр FILE_FLAG_OVERLAPPED
> и на

Этим и пользуюсь. Те у меня асинхронная работа и в потоке :)


 
Сергей М. ©   (2006-10-16 08:48) [88]


> Kolan ©   (16.10.06 08:30) [87]


> у меня асинхронная работа и в потоке


И зачем там нужна асинхронность ?
У тебя что, доп.поток еще чем-то занимается, кроме как работой с портом ?


 
Rem ©   (2006-10-16 09:25) [89]

У меня поток сам себя усыпляет:

while not Terminated do
begin
  if ReadIndex >= WriteIndex then
  begin
    Suspend;


Очень трудно разобраться с приведенными фрагментами кода, и я не знаю, что такое ReadIndex и WriteIndex, однако, думаю, удобнее реализовать таким образом:

while not Terminated do
begin
 while not Terminated and (ReadIndex >= WriteIndex) do
   Sleep(0); // 10, 20 или другая цифра по условию задачи
 {...}
end;

То есть, усыплять поток не надо будет...


 
Kolan ©   (2006-10-16 10:16) [90]


> У тебя что, доп.поток еще чем-то занимается, кроме как работой
> с портом ?

Нет
> Очень трудно разобраться с приведенными фрагментами кода,
>  и я не знаю, что такое ReadIndex и WriteIndex, однако,
> думаю, удобнее реализовать таким образом:

У меня там циклический буффер. Соотв индек по которому пишу данные и индекс по которому читаю и ищу начало/конец пакета.

> Sleep(0);

Гы :) Было и такое решение. Ну а зачем? А если данные часами не прийдут? Че он будет молотить в пустую?


 
Percent   (2006-10-16 10:27) [91]

Че он будет молотить в пустую?

Предлагаешь выключить компьютер? :-)

Поставь Sleep(50), и не мучайся...


 
Сергей М. ©   (2006-10-16 10:30) [92]


> Kolan ©   (16.10.06 10:16) [90]
> Нет


Тогда зачем асинхронный режим задействован ?


 
Kolan ©   (2006-10-16 10:42) [93]


> Тогда зачем асинхронный режим задействован ?

ХЗ. Дела я все это по статье:
http://morgeyz.elayne.ru/comlpt.htm

В конце статьи:

Теперь, но ОЧЕНЬ кратко, залезем в еще большие дебри. Предположим, что протокол обмена с Вашим устройством, подключенным к последовательному порту, очень сложен (передаются большие и сложные структуры данных). При этом Ваша программа должна получать уже полностью принятую и проверенную информацию. Предположим так же, что Ваша программа занимается очень большими и сложными вычислениями и ей нет времени отвлекаться на обработку ввода/вывода. Да и сложность ее такова, что встраивание фонового ввода/вывода сделает ее трудно прослеживаемой и неустойчивой. Чувствуете, куда я клоню? Правильно, к выделению всех тонкостей ввода/вывода в отдельный поток. Возможно выделение и в отдельную задачу, но в этом случае мы не получим никакой выгоды, а накладные расходы на переключение задач гораздо больше, нежели на переключение потоков в одной задаче.

Прям про мою задачу :) Вот я и выделил...


 
Kolan ©   (2006-10-16 10:42) [94]


>
> Предлагаешь выключить компьютер? :-)
>
> Поставь Sleep(50), и не мучайся...
>

Все же усыплять - красивше :) У меня тогда душа спокойна :)...


 
Kolan ©   (2006-10-16 10:49) [95]


> Ни че не пойму с этими исключениями...

Как бы так и продолжаю не понимать :)

Думаю сделаю так:
 В еще одном потоке "обработки" завиду очередь пакетов. При получении пакета буду туда добавлять и будить его. Поток будет просыпаться выбирать пкеты и обрабатывать. Ну как?

Дальше обработав пакет(массив) он будет создавать объект пакет.
И отдавать на обработку гл потоку. Опять же как тут быть? Опять Synchronize(DoSmth)? Получится тоже самое... Только теперь другой поток будет ждать пока DoSmth не завершится..


 
Сергей М. ©   (2006-10-16 10:54) [96]


> Kolan ©   (16.10.06 10:42) [93]


Цитата из той же статьи:

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

Твой доп.поток работает всего лишь с одним портом, а не с несколькими одновременно.

Чем в этом случае оправдан выбор асинхронного режима ?


 
Kolan ©   (2006-10-16 10:56) [97]


> Чем в этом случае оправдан выбор асинхронного режима ?

Смешно конечно звучит: Чтобы форма не висла... Работает пока и бог с ним. Тут бы это передеалть.. А с портом видно будет. Порт кстати пока не подводил...


 
Сергей М. ©   (2006-10-16 11:06) [98]


> Kolan ©   (16.10.06 10:56) [97]


> Смешно конечно звучит: Чтобы форма не висла


Ты даже не представляешь, насколько это смешно)..

Чтобы форма "не висла", ты как раз и задействовал доп.поток.
А уж как работает этот твой доп.поток с тем или иным устройством - синхронно или асинхронно - форме (еще точнее - основному потоку) отныне абсолютно фиолетово.
Так что сам собой напрашивается вывод - асинхр.режим выбран тобой от балды и  сложность его прогр.реализации (ощутимо повышенная по отношению к синхр.режима) ничем пока не оправдана.


 
Kolan ©   (2006-10-16 11:13) [99]


> асинхр.режим выбран тобой от балды и  сложность его прогр.
> реализации (ощутимо повышенная по отношению к синхр.режима)
> ничем пока не оправдана.

Ну не оправдан, знаю что до конца не разобрался. Сделал по статье - акуратно. Работатет не подводит. Уже сделано, зачем менять?


 
Сергей М. ©   (2006-10-16 11:42) [100]


> Kolan ©   (16.10.06 11:13) [99]



> Сделал по статье - акуратно


suspend твой в доп.потоке - тоже по статье ?)


 
Kolan ©   (2006-10-16 11:54) [101]


> suspend твой в доп.потоке - тоже по статье ?)

Причем тут это??? Я понимаю ветку ниасилили :)

Мы тут говорим НЕ о ПТОКЕ ЧНЕНИЯ ИЗ ПОРТА(который ессно не спит), а о другом потоке, Который ищет в полученых из порта данных пакет.


 
Сергей М. ©   (2006-10-16 12:12) [102]


> Kolan ©   (16.10.06 11:54) [101]


> ветку ниасилили


Эт точно)
В ней много шуму из ничего.

Если не вдаваться в подробности изначально неразумно спроектированной тобой логики разделения функциональности приложения (между потоками ее процесса), то ответ на вопрос был уже дан, и он прост как 2х2:

try
 synchronize(...)
except
... //никаких re-raise, если отсутствует перехват и обработка исключений уровнем выше !
end;


 
Kolan ©   (2006-10-16 12:17) [103]

Может мне для передечи сообщения, чтобы все осталось внутри модуля и не трогало гл. форму, создать формочку прямо в TConnectionManager

Те
TConnectionManager = class
 FForm: TForm;


А получив пакет я его скопирую и пошлю сообщение

procedure TConnectionManager.PackageReceivedEvent(Sender: TObject;
Package: array of Byte);
begin
 //Копирую
 PostMessage();
end;


Нормальный маривант?


 
Kolan ©   (2006-10-16 12:30) [104]

и сообщени передать Self те указательна экземпляр TConnectionManager, а форма вызовет:
TConnectionManger(Pointer).ProsessPackage // Ну или как там правильно преобразовать указатель в объект.

В итоге дальше модуля с TConnectionManger дело не пойдет. И Synchronize закончится быстро. :)

Но ответа я дождусь, а то опять перепахивать все :)


 
Ketmar ©   (2006-10-16 17:46) [105]

бр-р-р. что-то мне подсказывает, что ты спроектировал софт "от балды", совершенно не представляя, зачем там потоки, и что они должны делать. и как, собственно, вся эта механика работает. сорри, но у всех вопросов лапы растут явно оттуда. есть предложение: выспаться, плотно подумать и переписать всё заново. %-)


 
Kolan ©   (2006-10-16 18:12) [106]


> бр-р-р. что-то мне подсказывает, что ты спроектировал софт
> "от балды", совершенно не представляя, зачем там потоки,
>  и что они должны делать. и как, собственно, вся эта механика
> работает.

Все же некоторое представление о том что там да как имею. :)


> Kolan ©   (16.10.06 12:17) [103]

Дык это брр?

Итак я получил пакет. Как мне сделать дальше. Как спроектировать?

procedure TConnectionManager.PackageReceivedEvent(Sender: TObject;
Package: array of Byte);
begin
if Assigned(FConnectionManagerPackageReceivedEvent) then
  FConnectionManagerPackageReceivedEvent(Self, Package);  
end;


Система примерно такая
1. Есть главный менеджер в который композитно входит менеджер измерений(Он знает логику измерения).
2. В менеджере измерений есть менеджер устройства, который знает о протоколе.
3. Менеджер устройства использует менеджер связи(TConnectionManager), который обрабатывает данные и отправляет в порт.

Так вот форма в лучшем случае знает о Главном менеджере. Как быть? Сообщение посылать неудобно.

Как перепроектировать?


 
Kolan ©   (2006-10-16 18:22) [107]

Те я ка бы последовательно пользуюсь паттерном фасад.


 
Kolan ©   (2006-10-16 19:13) [108]

Короче, потом не говорите, что плохо  :)
TConnectionManager - точно должен быть фасадом. У него всего две функции предать пакет и выдать принятый, а там хот через сеть может передаваться. Делаю короче через окно(окно-поле этого менеджера) и сплю спокойно...


 
Percent   (2006-10-16 19:39) [109]

1. Есть главный менеджер в который композитно входит менеджер измерений(Он знает логику измерения).
2. В менеджере измерений есть менеджер устройства, который знает о протоколе.
3. Менеджер устройства использует менеджер связи(TConnectionManager), который обрабатывает данные и отправляет в порт.


И в чем проблема? Каждый менеджер пусть обрабатывает свой участок работы.
1. Менеджер связи - отсылает пакеты и ждет приходящих пакетов. Сделай у него события OnConnect, OnDisconnect, OnPacketReceived, OnError. И метод отправки пакета.
2. Менеджер устройства - пусть собирает пакеты для отправки и разбирает пакеты при пролучении.
3. Менеджер измерений пусть анализирует принятую информацию. И подготавливает данные измерений.

Ты бы хоть бы название софта озвучил бы. И логику его работы описал. То есть, для чего это все?


 
Leonid Troyanovsky ©   (2006-10-16 19:42) [110]


> Kolan ©   (16.10.06 18:12) [106]

> Как перепроектировать?


До главного менеджера боюсь, что не осилю, но,
для обработки ошибок в потоке могу предложить такой паттерн:

type
 EThreadException = class(Exception);

 TMyThread = class(TThread)
   procedure Execute; override;
 private
   ..
   Error: Exception;
   procedure ShowError;
   procedure ShowResult;
 end;

procedure TMyThread.ShowExcept;
begin
 Application.ShowException(Error);
end;

procedure TMyThread.Execute;
begin
 while not Terminated do
   try
      ..
      raise EThreadException.Create("..."); // если что-то не так
      ..
      Synchronize(ShowResult); // показываем результат
      ..
   except
     on E: EThreadException do // мы знаем, как исправить ситуацию
       begin
         Error := E;
         Synchronize(ShowExcept); // если нужен показ
         {корректирующие действия}
       end;
     on E: Exception do  // мы не знаем, как реагировать на другие ошибки
       begin
         Error:= E;
         Synchronize(ShowExcept); // показываем исключение
         Terminate; // завершаем поток
       end;
   end;
end;


Что произойдет, если исключение возникнет в ShowResult?
Если внутри метода нет обработчиков, исключение попадет в except потока. Если это известное исключение (EThreadException), то его можно
обработать и, возможно, поток продолжит работу.

Для неизвестных исключений продолжать поток смысла нет.

Схема может быть использована непосредственно
для тех потоков, которые отзываются на Termianate.
А, например, поток, ожидающий в ReadFile ввода не в состоянии
реагировать на установку Terminated, т.е., нуждается в
дополнительных управляющих сигналах.

Ну, и не должны потоки быть suspended.
Это для потока не рабочее состояние, а скорее отладочное.

--
Regards, LVT.


 
Kolan ©   (2006-10-16 20:01) [111]


> И в чем проблема? Каждый менеджер пусть обрабатывает свой
> участок работы.
Именно так они  и работают...


> Leonid Troyanovsky ©   (16.10.06 19:42) [110]
>
>

Благодарю. Идея понятная. Буду пользоваться.
Но в денном случае, опираясь на ваш код. В
Synchronize(ShowResult); мне надо лишь отправить пакет дальше... и Тут же вернуться. Те никаких исключений в потоке не будет.

Вот я и спрашиваю можно ли замутить с формой?


> Ну, и не должны потоки быть suspended.
> Это для потока не рабочее состояние, а скорее отладочное.
>

Буду медетировать на это.


 
Percent   (2006-10-16 20:06) [112]

Вот я и спрашиваю можно ли замутить с формой?

Перефразируй, пожалуйста...


 
Kolan ©   (2006-10-16 20:10) [113]

Вот короче этот злашастный менеджер целиком:

TConnectionManager = class
 private
   FCommPort: TAnisochronousComm;
   FCommReadThread: TAnisochronousCommReadThread;
   FPackageComposer: TPackageComposer;
   FPackageExtractor: TPackageExtractor;

   FConnectionManagerPackageReceivedEvent:
     TConnectionManagerPackageReceivedEvent;
 protected
   {Events}
   procedure CommReadEvent(Sender: TObject;
     ReadBytes: array of Byte);
   procedure SendPackageReadyEvent(Sender: TObject;
     Package: array of Byte);
   procedure PackageReceivedEvent(Sender: TObject;
     Package: array of Byte);
 public
   constructor Create;
   destructor Destroy; override;
   procedure SendPackage(Package: array of Byte);

   property ConnectionManagerPackageReceivedEvent:
     TConnectionManagerPackageReceivedEvent read
     FConnectionManagerPackageReceivedEvent write
     FConnectionManagerPackageReceivedEvent;
 end;


procedure TConnectionManager.CommReadEvent(Sender: TObject;
 ReadBytes: array of Byte);
begin
 FPackageExtractor.AddArray(ReadBytes);
end;

constructor TConnectionManager.Create;
begin
inherited Create;
 FCommPort := TAnisochronousComm.Create;
 FCommPort.Open;
 FCommReadThread := TAnisochronousCommReadThread.Create(FCommPort);
 FCommReadThread.CommReadEvent := CommReadEvent;
 FPackageComposer := TPackageComposer.Create(StartByte, EndByte, LastByte);
 FPackageComposer.SendPackageReadyEvent := SendPackageReadyEvent;
 FPackageExtractor := TPackageExtractor.Create(StartByte, EndByte);
 FPackageExtractor.PackageReceivedEvent := PackageReceivedEvent;
end;

destructor TConnectionManager.Destroy;
begin
 FCommPort.Free;
 FCommReadThread.Terminate;
 FCommReadThread.Resume;
 FPackageComposer.Free;
 FPackageExtractor.Terminate;
 FPackageExtractor.Resume;
 Sleep(10);
inherited Destroy;
end;

procedure TConnectionManager.PackageReceivedEvent(Sender: TObject;
 Package: array of Byte);
begin
 if Assigned(FConnectionManagerPackageReceivedEvent) then
   FConnectionManagerPackageReceivedEvent(Self, Package);  
end;


procedure TConnectionManager.SendPackage(Package: array of Byte);
begin
 FPackageComposer.AddArray(Package);
end;

procedure TConnectionManager.SendPackageReadyEvent(Sender: TObject;
 Package: array of Byte);
begin
 //
 LogManager.WriteString("Written to Com");
 LogManager.WriteByteArray(Package);
 //
 FCommPort.Write(Package, Length(Package));
end;


Те получив пакет я вызываю событие, FConnectionManagerPackageReceivedEvent

Там обрабатываю итд итп те в итоге все в Synchronize потоко будет.

А я терерь переделаю:
<След пост>


 
Kolan ©   (2006-10-16 20:32) [114]

Делаю форму:

TSynchronizationForm = class(TForm)
 public
   procedure SXPackageReady(var Msg: TMessage); message SX_PACKAGEREADY;
 end;


Она - поле класса:
TConnectionManager = class
 private
***
   FSynchronizationForm: TSynchronizationForm;
   FPackage: TByteArray;


При получении пакета:

procedure TConnectionManager.PackageReceivedEvent(Sender: TObject;
 Package: array of Byte);
begin
 SavePackage(Package);
 PostMessage(FSynchronizationForm.Handle, SX_PACKAGEREADY,
   Integer(Pointer(Self)), 0);

end;


При получении:
procedure TSynchronizationForm.SXPackageReady(var Msg: TMessage);
begin
(Msg.WParam as TConnectionManager).SendPackage;
end;


Вотэто идея. Проверит не могу, так как не могу правильно сохранить указатель на TConnectionManager(в смысле на его экземпляр). А затем вызвать функцию..

Процедура сохранения пакета:
procedure TConnectionManager.SavePackage(Package: array of Byte);
begin
 Move(Package, FPackage, SizeOf(Package));
end;


 
Kolan ©   (2006-10-16 20:32) [115]

Как правильно это сделать(Подчеркнутое)?


 
Leonid Troyanovsky ©   (2006-10-16 20:39) [116]


> Kolan ©   (16.10.06 20:01) [111]

> Но в денном случае, опираясь на ваш код. В
> Synchronize(ShowResult); мне надо лишь отправить пакет дальше.
> .. и Тут же вернуться. Те никаких исключений в потоке не


Если не нужна синхронизация (обработки пакета),
то поток может распределить блок нужного размера путем GetMem,
заполнить его данными и отправить его адрес (размер) путем
Post(Thread)Message главному потоку в форме WM_USER+x.
Главный же поток, по окончании обработки, удалит блок.

Можно и без сообщений, моделируя очередь посредством TThreadList.
Т.е., рабочий поток заполняет его адресами блоков, а главный поток
в Application.OnIdle его обрабатывает.

--
Regards, LVT.


 
Kolan ©   (2006-10-16 20:44) [117]


> Если не нужна синхронизация (обработки пакета),
> то поток может распределить блок нужного размера путем GetMem,
>
> заполнить его данными и отправить его адрес (размер) путем
> Post(Thread)Message главному потоку в форме WM_USER+x.
> Главный же поток, по окончании обработки, удалит блок.

Дааа, может Можно и не через GetMem, Но сообщение прийдет в форму.
А обработанное должно быть в TConnectionManager, а от Формы до него ого го см[106]. Что бы это сотворить надо предавать хендл формы во все эти классы.

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


 
Kolan ©   (2006-10-16 20:46) [118]

В жизни не создавал форм динамически, при

FSynchronizationForm := TSynchronizationForm.Create(nil);

получаю resourse TSynchronizationForm not found. Как избавится?


 
Leonid Troyanovsky ©   (2006-10-16 20:58) [119]


> Kolan ©   (16.10.06 20:44) [117]

> А обработанное должно быть в TConnectionManager, а от Формы
> до него ого го см[106].


Ну, я так далеко не заглядывал :)
Сделай компонент, который, с одной стороны, будет лежать
на форме (и знать, как с ней взаимодействовать), а, с другой
стороны - создаст поток и тоже будет с ним взаимодействовать.
Если хочется, то можно снабдить компонент окном, на манер TTimer,
в которое и будет осуществляться PostMessage.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2006-10-16 21:02) [120]


> Kolan ©   (16.10.06 20:46) [118]

> получаю resourse TSynchronizationForm not found. Как избавится?


Создавай потомка TForm.
Или, если нужно окно (невидимое), а не форма - AllocateHwnd.

--
Regards, LVT.



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

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

Наверх




Память: 0.72 MB
Время: 0.047 c
3-1159344071
DancerMan
2006-09-27 12:01
2006.11.26
SQL функция IIF


2-1162906856
AlexanderMS
2006-11-07 16:40
2006.11.26
Тонкости условной компиляции.


15-1162732832
Ученик чародея
2006-11-05 16:20
2006.11.26
Программа, которая может писать компютерные программы.


2-1163105993
Golikov
2006-11-09 23:59
2006.11.26
Абра катабра со шрифтами ??


2-1163026488
Repavel
2006-11-09 01:54
2006.11.26
НТТР запросы и ответы





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