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

Вниз

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

 
Zalm ©   (2009-09-06 16:47) [40]

отправить через TidTCPServer, забыл уточнить


 
Сергей М. ©   (2009-09-06 16:50) [41]


> у меня не получается


Показывай что делал ..
С подробными комментариями движений своей мысли для каждой строчки своего кода ..


 
Сергей М. ©   (2009-09-06 16:51) [42]


> отправить через TidTCPServer, забыл уточнить


Хоть через луну !

Ход своей мысли продемонстрируй ..


 
Zalm ©   (2009-09-06 21:13) [43]


unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, IdBaseComponent, IdComponent, IdCustomTCPServer, IdTCPServer, Buttons,
 idContext;

type
 TForm1 = class(TForm)
   Server: TIdTCPServer;
   procedure ServerConnect(AContext: TIdContext);
   procedure ServerExecute(AContext: TIdContext);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

 _Pack = Record
         Primary_handle : Cardinal;
         Secondary_handle : Cardinal;
         Primary_index : string[8];
         Secondary_index : string[8];
        End;

 {функция для того что бы составить пару из подключений}
 Function Connect_to_Clients( Handle : cardinal; index : string):boolean;
 {получение хэндла "соседа" пары, отправили свой handle, в ответе     получили его handle}
 Function GetHandleByHandle(Handle : cardinal):Cardinal;
 { "переброс" команд, отправляем свой handle, и что хотели отправить "соседу"}
 Procedure Transfer(handle : cardinal; str: string);

var
 Form1: TForm1;
 Pack : _Pack;
 Clients : Array of _Pack;
 Clients_count : integer;

implementation

{$R *.dfm}

procedure TForm1.ServerConnect(AContext: TIdContext);
var
str : string;
begin
AContext.Connection.Socket.WriteLn("Welcame"+#13+"Index[8]: ");
Str:=AContext.Connection.Socket.ReadLn();
if length(str)<>8 then
 begin
  AContext.Connection.Socket.WriteLn("Error length index");
  AContext.Connection.Disconnect;
 end
else
 begin
  if Connect_to_clients(Acontext.Connection.Socket.Binding.Handle,str) then
   begin
    Acontext.Connection.Socket.WriteLn("Start transfer");
   end
  else
   begin
    Acontext.Connection.Socket.WriteLn("Error registration");
    AContext.Connection.Disconnect;
   end;
 end;
end;

Function Connect_to_Clients( Handle : cardinal; index : string):boolean;
var
i : integer;
register_ : boolean;
begin
Result:=false;
for i:=0 to Clients_count-1 do
 begin
  if ((Clients[i].Primary_index=index)or(Clients[i].Secondary_index=index)) then
   begin
    if Clients[i].Primary_index=index then
     begin
      Clients[i].Secondary_handle:=Handle;
      Clients[i].Secondary_index:=index;
      result:=true;
      exit;
     end;
    if Clients[i].Secondary_index=index then
     begin
      Clients[i].Primary_handle:=Handle;
      Clients[i].Primary_index:=index;
      result:=True;
      exit;
     end;
   end;
 end;
inc(clients_count);
SetLEngth(Clients,Clients_count);
Clients[Clients_count-1].Primary_handle:=handle;
Clients[Clients_count-1].Primary_index:=Index;
Result:=True;
end;

procedure TForm1.ServerExecute(AContext: TIdContext);
var
msg : string;
i : integer;
begin
msg:=AContext.Connection.Socket.ReadLn();
if msg="\handle\" then
 begin
  AContext.Connection.Socket.WriteLn(IntTOStr(AContext.Connection.Socket.Binding.H andle));
  exit;
 end;
if msg="\clients\" then
 begin
  for i:=0 to CLients_count-1 do
   begin
    AContext.Connection.Socket.WriteLn(
    "-----------------"+#13+"Couple "+IntToStr(i+1)+#13+
    "PH: "+IntToStr(Clients[i].Primary_handle)+#13+
    "PI: "+Clients[i].Primary_index+#13+
    "SH: "+IntToStr(Clients[i].Secondary_handle)+#13+
    "SI: "+Clients[i].Secondary_index);
   end;
   AContext.Connection.Socket.WriteLn("Done. "+IntToStr(Clients_count)+" couples.");
  exit;
 end;
if msg="\couples\" then
 begin
  AContext.Connection.Socket.WriteLn(INtToStr(Clients_count)+" couples.");
  exit;
 end;
if msg="\GetHandleByHandle\" then
 begin
  AContext.Connection.Socket.WriteLn(IntToStr(GetHandleByHandle(AContext.Connectio n.Socket.Binding.Handle)));
 end;
Transfer(AContext.Connection.Socket.Binding.Handle,msg);
end;

Procedure Transfer(handle : cardinal; str: string);
var
_handle : cardinal;
begin
_handle:=GetHandleByHandle(handle);
{...по идее тут отправка str подключению с известным нам _handle,
 это и есть товарищ из пары, вот только как отправить таким спобом
 этого я не знаю..:( }
end;

Function GetHandleByHandle(Handle : cardinal):Cardinal;
var
i : integer;
begin
result:=0;
for i:=0 to Clients_count-1 do
 begin
  if Clients[i].Primary_handle=handle then
   begin
    result:=Clients[i].Secondary_handle;
    exit;
   end;
  if Clients[i].Secondary_handle=handle then
   begin
    Result:=Clients[i].Primary_handle;
    exit;
   end;
 end;
end;

end.


вот, вроде как бы всё работает, но до определенного затыка в процедуре Transfer.


 
Сергей М. ©   (2009-09-07 09:01) [44]

Тихий ужас..

Хендлы какие-то куда-то отправляются ..

Ты в состоянии изложить формальное описание разработанного тобой протокола инф.обмена между клиентами и сервером ?


 
Сергей М. ©   (2009-09-07 10:13) [45]

За каким тебе понадобились хендлы, если у тебя есть список уникальных объектов IdTCP.Server.Connections, каждый из которых отражает контекст соединения сервера с одним из его активных клиентов ?


 
Zalm ©   (2009-09-07 12:52) [46]

да что есть? ничего там нет, просил же показать то о чем вы всё время говорите, так вы не можете.
Зачем вам всё время нужен этот протокол я никак не понимаю, у меня проблема совсем в другом.


 
Zalm ©   (2009-09-07 12:57) [47]


> если у тебя есть список уникальных объектов IdTCP.Server.
> Connections

У вас может быть и есть, а у меня нету. есть только Server.Contexts в котором есть LockList в котором уже я ничего не нашел.
Вот просил же хоть что-то показать конкретное, а вы мне только наводящие вопросы задаете, которые ни на что не наводят меня(


 
Сергей М. ©   (2009-09-07 13:13) [48]


> Зачем вам всё время нужен этот протокол я никак не понимаю


Для того чтобы понять "язык", на котором ты пытаешься заствить разговаривать своих клиентов со своим сервером - что, кому, когда, в каком формате и при каких условиях передается/принимается

Пойми, наконец, что без формализованного прикладного протокола инф.обмена ничего путного у тебя не получится. Любую сколь-либо серьезную сетевую разработку следует начинать с листа бумаги и авторучки, а не со слепого тыканья в компонентах.


> у меня проблема совсем в другом


Не надо себе их, проблемы эти, создавать, тогда и не придется их потом героически преодолевать.

Взять хотя бы элементарное, о чем я у тебя уже спросил в [45] ..


 
Сергей М. ©   (2009-09-07 13:21) [49]


> у меня нету. есть только Server.Contexts


Да ну какая разница ?
пусть будет не Connections, а Contexts - суть свойства от  этого не меняется.


> LockList в котором уже я ничего не нашел


Что и где ты искал из того что не нашел ?


 
Сергей М. ©   (2009-09-07 13:23) [50]


> вопросы задаете, которые ни на что не наводят меня


Это печально. Очень.


 
Anatoly Podgoretsky ©   (2009-09-07 13:24) [51]

> Zalm  (07.09.2009 12:57:47)  [47]

Так вопросы задаются, потому что от тебя не поступило полной информации,
если не ты, то мы.


 
Сергей М. ©   (2009-09-07 13:36) [52]


> Zalm


Ты вообще осознаешь, что работу с каждым из своих клиентов IdTCP-сервер осуществляет в отдельном дополнительном треде ?
Судя по

> У TServerSocket было проще всё, ну или понятней

ты обязан это осознавать, ибо в режиме stThreadBlocking TServerSocket работает точно так же как и IdTCP-сервер.
Если осознаешь, то почему не выполняешь обязательную синхронизацию доступа к потоконебезопасным ресурсам, таким как, например, массив Clients, переменную Clients_count ?


 
Zalm ©   (2009-09-07 13:39) [53]

Ну нету никакого протокола. В коде же видна идея как осуществляется обмен. При подключении "зарегистрировали" клиента, и всё, потом другой клиент подключается, такая же процедура, если они вводят один и тот же индекс, они получаются в паре, и сервер сразу передает между ними абсолютно всё что шлют (текст). Клиенты к этому серверу-посреднику обратиться никак не могут, ибо незачем.


> За каким тебе понадобились хендлы, если у тебя есть список
> уникальных объектов IdTCP.Server.Connections, каждый из
> которых отражает контекст соединения сервера с одним из
> его активных клиентов ?

а как записывать какие-то данные о клиенте что бы потом знать кто с кем в паре? Записать хендл мне показалось более целесообразно так как я видел функцию BindingByHandle, я подумал что можно по обработчику пробиться до сокета который он обрабатывает. Но идея завалилась.
А толку записать порт и адрес как вы говорили? что мне потом с ними делать?


> > LockList в котором уже я ничего не нашелЧто и где ты искал
> из того что не нашел ?

Ну вот Server.Contexts.LockList  а дальше что? есть Items[index:integer]:pointer, это единственное что вызывает какое-то внимание, но сделать тоже ничего не получается с этим. Так что чем может помочь этот LockList я не понимаю, и вы подсказать не можете.

видел кусок из примера для инди 9


List := tcpServer.Threads.LockList;
 try
   for Count := 0 to List.Count -1 do
   try
     TIdPeerThread(List.Items[Count]).Connection.WriteLn(Msg);
   except
     TIdPeerThread(List.Items[Count]).Stop;
   end;
 finally
   tcpServer.Threads.UnlockList;
 end;

Они себе в переменную типа TList копируют себе этот LockList и рассылают всем сообщение. ТОлько что такое  TIdPeerThread я не знаю, у меня такого нет. У них есть еще IdThreadMgrDefault1: TIdThreadMgrDefault; это в описании, тоже не знаю что это, у меня ткого нет.
Вобщем жаль что не хотите ничего конкретного подсказать.


 
Zalm ©   (2009-09-07 13:45) [54]


> Ты вообще осознаешь, что работу с каждым из своих клиентов
> IdTCP-сервер осуществляет в отдельном дополнительном треде
> ?

это да, это я знаю.
> почему не выполняешь обязательную синхронизацию доступа
> к потоконебезопасным ресурсам, таким как, например, массив
> Clients, переменную Clients_count ?

не знаю, я такого раньше не делал, проблем как мне казалось из-за этого не было. да и как это синхронизацию я не знаю, я с этим не сталкивался к сожалению


 
Медвежонок Пятачок ©   (2009-09-07 13:48) [55]

Ну нету никакого протокола.  

У тебя ничего не получится.


 
Сергей М. ©   (2009-09-07 13:51) [56]


> Ну нету никакого протокола


Ты прикидываешься или где ?

Как это "нету" ?

А это, к примеру, что по-твоему


> "Welcame"


?

Почему именно "велцаме" у тебя фигурирует, а не "Здарофф, чувак ! Ет я, сервер, с тобой разговариваю" ?


 
Сергей М. ©   (2009-09-07 13:57) [57]


> Ну вот Server.Contexts.LockList  а дальше что?


Ну и что толку тебе объяснять про "дальше что", если межпоточная синхронизация и защита ресурсов для тебя что новые ворота ?


 
Сергей М. ©   (2009-09-07 14:04) [58]


> что такое  TIdPeerThread я не знаю, у меня такого нет


В 10-ке элементами этого списка явл-ся объекты класса TIdContext


 
Медвежонок Пятачок ©   (2009-09-07 14:04) [59]

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


 
Сергей М. ©   (2009-09-07 14:12) [60]


> про ресурсы ему еще рано


Тогда и делать ему пока нефига в индейских серверах. Не по сеньке шапка.
Есть TServerSocket, есть stNonBlocking - там ему "было проще всё, ну или понятней".
Какого лешего ему понадобилось лезть в индейские мультипоточные блокирующие дебри - до сих пор не понятно.
Было бы хотя бы вразумительное обоснование выбора Инди - был бы тогда и стимул вдалбливать ему про синхронизацию и прочую мультипоточную требуху. А так  - что о стенку горох)


 
Медвежонок Пятачок ©   (2009-09-07 14:57) [61]

правильная конфигурация:
сервер постоянно читает запросы клиентов.
получив запрос клиента, отправляет ему ответ, затем снова читает/ждет следующий запрос.

рассылка всем клиентам сообщения по инициативе сервера:
сервер получает текст сообщения от администратора и ничего никуда не посылает. Запоминает его и ждет, когда клиент запросит " А нет ли для меня какого-нить сообчения?"
Получив подобный запрос клиента, сервер отдаети ему сообщение прямо в обработчике команд, без всяких локлистов и прочей ерунды.


 
Сергей М. ©   (2009-09-07 15:09) [62]


> без всяких локлистов и прочей ерунды


В мультипоточном сервере без lock-тряхомудии вряд ли обойтись)
Другой вопрос - она нада ли автору, мультипоточность та самая ..
Впрочем, он и сам не знает.


 
Медвежонок Пятачок ©   (2009-09-07 15:14) [63]

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

Но нах юный друг хочет чтобы и сервер и клиент были одновременно и сервером им клиентом.


 
Сергей М. ©   (2009-09-07 15:34) [64]


> лочить ничего не надо


Ну как же не надо ?


> все происходит либю в OnExecute, либо в диспетчерах прикладных
> команд


Все это происходит в контексте треда, обслуживающего текущий коннект.
И тред этот и обслуживаемый им коннект полностью изолированы от прочих тредов сервера, обслуживающих как прочие коннекты, так и внутрикухонные нужды сервера. Все эти треды сервера так или иначе, рано или поздно обязательно пересекутся на доступе к тому или иному потоконебезопасному ресурсу, а, значит, потребуется синхронизация. Как она д.б. реализована - то ли локами, то ли синхр.сообщениями, то ли задействованием иных объектов илои способов синхронизации - другой вопрос.


 
Медвежонок Пятачок ©   (2009-09-07 15:45) [65]

Ну это само собой разумеется.
Но я-то про Среадс.ЛокЛист говорил конкретно.
Точнее про то, что он почти никогда не нужен правильному серверу.


 
Сергей М. ©   (2009-09-07 15:47) [66]


> про то, что он почти никогда не нужен правильному серверу


С этим солидарен.


 
Zalm ©   (2009-09-07 17:05) [67]

правильный сервер... я бы вобще не назвал то что мне нужно сервером.
Вобщем ладно, спасибо вам за участие в теме, понял что помощи не будет


 
Медвежонок Пятачок ©   (2009-09-07 17:17) [68]

фигасе заявки. "помощи не будет".


 
Сергей М. ©   (2009-09-07 17:18) [69]


> я бы вобще не назвал то что мне нужно сервером


Обзови его хоть горшком - как он был сервером, так он им и останется.
Его задача - обслуживать (to serve) клиентов, если они не в состоянии сами себя обслужить.


> помощи не будет


Тебе уже 68 постов только и делают, что помогают, а ты все не внемлешь.


 
Сергей М. ©   (2009-09-07 17:30) [70]


> если бы я писал через TServerSocket  я бы не задавал таких
> тупых вопросов


Глубоко в этом сомневаюсь.
Были бы другие, но не менее тупые.


 
Zalm ©   (2009-09-07 17:48) [71]

Server.Bindings.BindingByHandle(handle : cardinal)

а это что делает?


 
Zalm ©   (2009-09-07 17:51) [72]

вот что сложного ответить на вопрос как отправить клиенту строку зная либо хендл, либо его адрес, либо его индекс подключения?)


 
Zalm ©   (2009-09-07 18:07) [73]

что вобще сложного в том сервере который мне нужен? та же структура что и у сервера аси, получил передал сразу вот и всё...


 
Медвежонок Пятачок ©   (2009-09-07 18:10) [74]

получил передал сразу вот и всё...

не сразу, а только по запросу того, кому это предназначалось.


 
Медвежонок Пятачок ©   (2009-09-07 18:14) [75]

Вот я клиент твоей аси.
И Сергей М. тоже клиент.

Я нажимаю кнопку и запрашиваю инфо о контакте Сергея М.
В это время он мне шлет сообщение "Превет Медвет"
Сервер его получает и тут же сразу же мне его шлет.
А я в это время отправил запрос о его профиле и жду его.
А в ответ мне вместо данных его профиля приходит "Превет Медвет".
Я (точнее твой чудо-клиент аси) при этом в полной уверенности что:
1. Получил не сообщение, а инфу о профиле Сергея М
2. Мне не пришло текстовое сообющение от Сергея М

дальше разжевывать надо?


 
Zalm ©   (2009-09-07 18:23) [76]

ася что ли сидит и спрашивает у сервера есть ли для неё сообщения?

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


 
Медвежонок Пятачок ©   (2009-09-07 18:27) [77]

ася что ли сидит и спрашивает у сервера есть ли для неё сообщения?

Ты лучше спроси как она вообще получает сообщения ничего не запрашивая (якобы) и ничего не читая (якобы).


 
Медвежонок Пятачок ©   (2009-09-07 18:29) [78]

Хотя этот вопрос лишний.
Ты попробуй сначала выкрутится из ситуации, что описана у меня в [75].

Когда в ответ на запрос информации о контакте приходит не инфа о контакте, а "Превет Медвет".


 
Zalm ©   (2009-09-07 18:34) [79]

ну а что там выкручиться, сложности никакой.
например синтаксис для собщения MSG_<сообщение>, а для инфы INFO_<инфа>, и какой тут напряг? придет себе сообщение, будет оно как сообщение, а инфу по-прежнему ждем


 
Сергей М. ©   (2009-09-07 18:38) [80]


> Zalm ©   (07.09.09 17:51) [72]


А что ты хотел видеть в кач-ве ответа на этот вопрос ?


> а это что делает?


"Это" возвращает binding-структуру с интересующим значением поля handle.


> та же структура что и у сервера аси, получил передал сразу
> вот и всё


Это тебе "сервер ася" сказал ?
Или ты изучил документацию ?


> вот что сложного ответить на вопрос как


А что ты хотел увидеть в кач-ве ответа на вопрос ?
Код ?
Он тебе не поможет, уверяю тебя.
Ты нишиша в нем не поймешь.
Даже если ты сдуешь его "один в один", он у тебя работать не будет.



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

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

Наверх





Память: 0.65 MB
Время: 0.009 c
2-1259921265
Alexxx
2009-12-04 13:07
2010.01.24
indy &amp; 503


2-1259642819
d@nger
2009-12-01 07:46
2010.01.24
помогите написать SQL запрос (Firebird)


2-1259750612
Matveih1
2009-12-02 13:43
2010.01.24
Как передать соединение BDE в другой модуль.


15-1258446035
_
2009-11-17 11:20
2010.01.24
Довлоадеры. Какой выбрать?


2-1259779619
Danco
2009-12-02 21:46
2010.01.24
Смена запуска Unit





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