-
Здравствуйте, как у TIdCmdTCPServer можно всем клиентам разослать сообщение? Надо например каждому отослать команду. Это должно быть естественно в цикле, только я не знаю как и где. У TServerSocket было проще всё, ну или понятней. 1)Вот например у меня есть кнопка на сервере, как сделать чтоб ы при нажатии на кнопку каждому подключению что-то отправить, и что бы узнать его адрес там и тд? 2) Как узнать ip и handler подключения? и в каком евенте... если в OnConnect то я не опнля как... 3) Как вне событий отправить текст на подключение с известным адресом\обработчкиом? Буду очень благодарен за помощь.
-
Внимание! Здесь обсуждаются вопросы, связанные с разработкой компонентов, редакторов свойств, редакторов компонентов и экспертов IDE. Вопросы по поиску и использованию готовых компонентов, редакторов или экспертов являются нарушением тематики и могут быть удалены.
-
Зависит от версии Инди
-
Извиняюсь перед админами.
Сергей, версия 10
-
и что бы узнать его адрес там и тд?
Адрес и тд узнавать не надо. Он уже есть в сессии подключенного клиента
-
> Zalm
У любого наследника TIdCustomTCPServer, каковым является и TIdCmdTCPServer, есть публичное св-во Contexts, представляющее собой потокозащищенный список потоков, в контекстах каждого из которых исполняется каждое из активных соединений с клиентами.
Каждый из элементов этого списка есть объект класса TIdPeerThread, у которого есть объектное св-во Connection, со всеми вытекающими)
-
как раз таки я не заметил что бы из COnnection что-то вытикало, я его видел, но ничего конкретного из него мне получить неудалось
-
чтобы вытекание было заметным надо после коннекшена поставить точку и подождать подсказки иде
-
Да уж, слона-то ты и не приметил)
А справка, надо понимать, тоже молчит ?
-
"Server.Contexts" вот тут ниче нет явно
"Server.Bindings.Items[0].Handle" вот так можно что-то добиться, но тут УЖЕ надо знать индекс подключения, да и адрес не узнать....
а справки у меня нету)
-
мало точек поставил
-
да и адрес не узнать....
Интересно, что ты будешь делать, если узнаешь этот адрес.
-
> "Server.Contexts" вот тут ниче нет явно
Что значит "нече нет явно" ?
> Server.Bindings
Это из другой оперы, к клиентским коннектам оно отношения не имеет.
> справки у меня нету
Мыши сгрызли ?)
Коли нету - купи, найди, укради. Без справки ничего путного не получится - так и будешь тыкаться как слепой котенок)
-
> Сергей М. (31.08.2009 16:43:12) [12]
А не умрет ли он скорее со справкой, ведь речь про ИНДИ
-
> Anatoly Podgoretsky © (31.08.09 16:56) [13]
Ну дык еще и исходники всегда перед носом) Довольно сложно сыграть в ящик, имея справку+исходники ..
-
примеры у меня ткоа на 9-ю версию есть, там иначе всё написано.
-
Скачай для 10-ки, в чем проблема ? Заодно и справку скачай.
-
и все же загадка. зачем ему понадобился адрес клиента.
-
да адрес клиента не при чем, это я просто сказал что например как узнать. Главное как клиента идентифицировать что бы потом знать кто есть кто...
-
коннекшен - это и есть "кто"
-
угу, если бы я писал через TServerSocket я бы не задавал таких тупых вопросов.
Ну вот разве что это что-то дельное AContext.Connection.Socket.Binding.Handle; и адрес там можно узнать. Тока пользы никакой для меня, в Server.Contexts я так и не нашел куда можно этот значение приспособить... Тока в Server.Bindings.BindingByHandle(HND).SendTo(); можно пихнуть... и то не получилось:(
а примеры на 10-Ю версию не могу найти((
-
Дядя, в метод OnExecute сервера тебе передано нечто. Нечто это бывает разным в разных версиях инди. Вот это нечто и есть то что тебе надо. А так же все что вложено в этот тип.
-
для десятки это будет так: IdCmdTCPServer1Execute(AContext: TIdContext);
вот этот контекст и есть то, что чего ты весь день ищешь
-
а мне Execute не надо, я там ничего не пишу, всё только в командным обработчиках. А через OnConnect просто хотел записывать данные в массив о подключившихся что бы их как-то различать потом. только вот как записать в массив что-то конкретное из события OnConnect я так и енп онял... Не подскажете?
-
> мне Execute не надо, я там ничего не пишу
А куда ты денешься с подводной лодки ? Придется писать.
> как записать в массив что-то конкретное из
Не надо ничего никуда "пихать" - все уже давным-давно "напихано".
В списке Connections.LockList каждый элемент - это TIdPeerThread. У TIdPeerThread есть объектное св-во Connection: TIdSocketHandle У объекта TIdSocketHandle есть св-ва PeerIP и PeerPort - адрес и порт клиента. Эта комбинация всегда уникальна, и этого достаточно для однозначной идентификации клиента. Кр.того, у объекта TIdSocketHandle есть send/recv-методы для коммуникации с клиентом.
-
эх так и знал что вся подстава в этом LockList ((( я его открыл посмотрел и забил, ибо не показалось что как-то с сервером связано.
А зачем обязательно в Execute писать?
Спасибо большое, щас пойду пробовать.
-
Я наверное что-то не понимаю... но у меня нельзя так сделать из любого места. Вот допустим я знаю порт и адрес, как вы сказали, Потом отсылаю в процедуру, адрес и порт, а когда хочу написать в процедуре Server.Connections то такого нет, есть только Server.Contexts.LockList а в лок-листе нет опять же свойства ни сокетов ни Connections... опять я чего-то не понял? :(
-
ты сначала вот над этим порассуждай: присоединился клиент и висит на сервер. затем он отправляет на сервер команду. серверу в это время приходит в голову разослать всем клиентам сообщение и он это делает. а клиент в это время команду уже отправил и ждет свой законный ответ именно на нее. вместо этого он получает кусок байтов, которые он интерпретирует как ответ на команду.
а на самом деле там у тебя там дрова лежат.
ps для обмена между сервером и клиентом нужно стрго следовать какому-то стандартному протоколу, либо придумать свой протокол и следовать ему.
-
> зачем обязательно в Execute писать?
А ты и в Execute не напишешь. Execute вызывается только если у сервера список CommandHandlers пуст, а он у тебя заведомо не пуст, ибо нафих тогда нужен TidCmdTCPServer ? Ты пойми главное - TidCmdTCPServer не предназначен для выкрутасов задуманного тобой вида, он заточен и призван работать в режиме "команда клиента -> ответ сервера как результат выполнения этой команды". На то как раз ComandHandler'ы у него и существуют.
-
А какие у меня выкрутасы?) вобще задача у меня такая, нужен сервер который будет как бы точкой переброса, короче надо что бы он мог создавать "пары" из соединений, и транслировать между ними (между членами в паре) трафик, в данном случае любой текст, который любой член этой пары захочет послать. Например один клиент передает команду на сервер, сервер принимает и смотрит от кого пришло и пересылает это тому кто находится в паре с этим клиентом. Да, такая спицифическая система) Тогда что вы бы посоветовали какой компонент использовать? Подскажите пожалуйста как лучше можно было бы сделать.
-
> как лучше можно было бы сделать
Пока не будет внятного разработанного тобой протокола информационного обмена, рассуждения на тему "лучше-хуже" лишены смысла.
-
эх.. а конкретнее? что сложного сделать сервер котоый будет просто текст перебрасывать? ему же ничего не надо трогать, получил, передал дальше, и всё. Как я понял уже через TIdCmdTCPServer это не очень удобно делать.
-
> что сложного сделать сервер котоый будет просто текст перебрасывать?
А нашиша тогда выбрал TIdCmdTCPServer, если требуется "просто текст перебрасывать" ? Почекму не TIdTCPServer ? И чем так уж не угодил тот же самый TServerSocket, тем более что там для тебя "проще всё, ну или понятней" ?
> а конкретнее?
Вот сейчас мы с тобой "разговариваем" при использовании протокола информационного обмена HTTP. А ты разработал свой протокол ?)
-
Я знаю что такое HTTP и как работает... Если это можно назвать "разработал", то можно и так, но только не для обмена с сервером "пересылки", а с конечными точками. TServerSocket мне не нравится так придется все потоки в ручную писать и много вобще придется писать. А на TIdTCPServer думаю проще будет, он и потоки сам создает же, и всё лучше... так что попробую через него.
Еще вопрос такой мб сторонний немного, к этой теме относится только тем что тоже работа с сетью. Можно Как-то закосить сервер под сервер аси? что бы например конектится не к login.icq.com, а например к моему сервру, и что бы он клиенту контакт лист выдал и мог читать что этот клиент отправит на сервер? и не более. Больше ничего серверу не требуется кроме как выдать конаткт лист с заранее вписанными на сервер контактами, и читать что этим контактам будет слать клиент. То есть есть один сервер и один клиент.. ну думаю вы поняли задачу..)
-
> но только не для обмена с сервером "пересылки", а с конечными > точками
А "конечные точки" у тебя между собой напрямую не взаимодействуют. Они же у тебя "разговаривают" через твой сервер-посредник, так что и речь может идти не иначе как о протоколе инф.обмена между клиентами и сервером-посредником.
> TServerSocket мне не нравится так придется все потоки в > ручную писать
В смысле ?
> Можно Как-то закосить сервер под сервер аси?
Можно.
-
что сложного сделать сервер котоый будет просто текст перебрасывать?
не сложно. сложно написать клиента который понял бы все перебрасываемое ему. хотя тоже не сложно (если самому себе не рыть ям)
-
я знаю как всё написать, просто пока не определился точно к компонентом.
Читая протокол я не понял какие команды сначала надо слать с сервера клиенту когда он подключится тока... я подключался с телефона к серверу, он подключается и молчит и чего-то ждет... где можно прочитать коротко какая последовательность компанд друг другу дожна быть что бы они подключились? Подскажете?
-
> Читая протокол
Как можно читать то, что ты еще не написал ?)
> какие команды сначала надо слать с сервера клиенту
А что, клиент нуждается в каких-то командах ? Нахрена, спрашивается, тогда нужен сервер, если клиенты готовы исполнять его прихоти ?)
> какая последовательность компанд друг другу дожна быть что > бы они подключились?
Никакая. Ты же сам утверждаешь, что якобы "подключался с телефона к серверу", при этом ни ты серверу, ни сервер тебе не посылал никаких "команд") Чудеса ?)
-
> Ну дык еще и исходники всегда перед носом)
Ну ты и садист.
-
ох... вернулся к этой тему.. что-то я никак не пойму:( у меня не получается никак отправить кому-то что-то за пределы его потока.
можете пожалуйста если вам не сложно показать кусок конкретного кода как отправить кому-то что-то не из его потока? Я был бы очень благодарен
-
отправить через TidTCPServer, забыл уточнить
-
> у меня не получается
Показывай что делал .. С подробными комментариями движений своей мысли для каждой строчки своего кода ..
-
> отправить через TidTCPServer, забыл уточнить
Хоть через луну !
Ход своей мысли продемонстрируй ..
-
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
public
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;
Function GetHandleByHandle(Handle : cardinal):Cardinal;
Procedure Transfer(handle : cardinal; str: string);
var
Form1: TForm1;
Pack : _Pack;
Clients : Array of _Pack;
Clients_count : integer;
implementation
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);
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.
-
Тихий ужас..
Хендлы какие-то куда-то отправляются ..
Ты в состоянии изложить формальное описание разработанного тобой протокола инф.обмена между клиентами и сервером ?
-
За каким тебе понадобились хендлы, если у тебя есть список уникальных объектов IdTCP.Server.Connections, каждый из которых отражает контекст соединения сервера с одним из его активных клиентов ?
-
да что есть? ничего там нет, просил же показать то о чем вы всё время говорите, так вы не можете. Зачем вам всё время нужен этот протокол я никак не понимаю, у меня проблема совсем в другом.
-
> если у тебя есть список уникальных объектов IdTCP.Server. > Connections
У вас может быть и есть, а у меня нету. есть только Server.Contexts в котором есть LockList в котором уже я ничего не нашел. Вот просил же хоть что-то показать конкретное, а вы мне только наводящие вопросы задаете, которые ни на что не наводят меня(
-
> Зачем вам всё время нужен этот протокол я никак не понимаю
Для того чтобы понять "язык", на котором ты пытаешься заствить разговаривать своих клиентов со своим сервером - что, кому, когда, в каком формате и при каких условиях передается/принимается
Пойми, наконец, что без формализованного прикладного протокола инф.обмена ничего путного у тебя не получится. Любую сколь-либо серьезную сетевую разработку следует начинать с листа бумаги и авторучки, а не со слепого тыканья в компонентах.
> у меня проблема совсем в другом
Не надо себе их, проблемы эти, создавать, тогда и не придется их потом героически преодолевать.
Взять хотя бы элементарное, о чем я у тебя уже спросил в [45] ..
-
> у меня нету. есть только Server.Contexts
Да ну какая разница ? пусть будет не Connections, а Contexts - суть свойства от этого не меняется.
> LockList в котором уже я ничего не нашел
Что и где ты искал из того что не нашел ?
-
> вопросы задаете, которые ни на что не наводят меня
Это печально. Очень.
-
> Zalm (07.09.2009 12:57:47) [47]
Так вопросы задаются, потому что от тебя не поступило полной информации, если не ты, то мы.
-
> Zalm
Ты вообще осознаешь, что работу с каждым из своих клиентов IdTCP-сервер осуществляет в отдельном дополнительном треде ? Судя по
> У TServerSocket было проще всё, ну или понятней
ты обязан это осознавать, ибо в режиме stThreadBlocking TServerSocket работает точно так же как и IdTCP-сервер. Если осознаешь, то почему не выполняешь обязательную синхронизацию доступа к потоконебезопасным ресурсам, таким как, например, массив Clients, переменную Clients_count ?
-
Ну нету никакого протокола. В коде же видна идея как осуществляется обмен. При подключении "зарегистрировали" клиента, и всё, потом другой клиент подключается, такая же процедура, если они вводят один и тот же индекс, они получаются в паре, и сервер сразу передает между ними абсолютно всё что шлют (текст). Клиенты к этому серверу-посреднику обратиться никак не могут, ибо незачем. > За каким тебе понадобились хендлы, если у тебя есть список > уникальных объектов 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; это в описании, тоже не знаю что это, у меня ткого нет. Вобщем жаль что не хотите ничего конкретного подсказать.
-
> Ты вообще осознаешь, что работу с каждым из своих клиентов > IdTCP-сервер осуществляет в отдельном дополнительном треде > ?
это да, это я знаю. > почему не выполняешь обязательную синхронизацию доступа > к потоконебезопасным ресурсам, таким как, например, массив > Clients, переменную Clients_count ?
не знаю, я такого раньше не делал, проблем как мне казалось из-за этого не было. да и как это синхронизацию я не знаю, я с этим не сталкивался к сожалению
-
Ну нету никакого протокола.
У тебя ничего не получится.
-
> Ну нету никакого протокола
Ты прикидываешься или где ?
Как это "нету" ?
А это, к примеру, что по-твоему
> 'Welcame'
?
Почему именно "велцаме" у тебя фигурирует, а не "Здарофф, чувак ! Ет я, сервер, с тобой разговариваю" ?
-
> Ну вот Server.Contexts.LockList а дальше что?
Ну и что толку тебе объяснять про "дальше что", если межпоточная синхронизация и защита ресурсов для тебя что новые ворота ?
-
> что такое TIdPeerThread я не знаю, у меня такого нет
В 10-ке элементами этого списка явл-ся объекты класса TIdContext
-
про ресурсы ему еще рано. он кажется самого главного не понял: если хочется, чтобы сервер имел возможность отправки сообщения в произвольный момент времени, то клиент такого сервера должен постоянно висеть в процедуре чтения буфера и ни на что иное не отвлекаться. При этом он теряет возможность отправлять на сервер что-либо по своей инициативе. Причем на все время своей сессии.
-
> про ресурсы ему еще рано
Тогда и делать ему пока нефига в индейских серверах. Не по сеньке шапка. Есть TServerSocket, есть stNonBlocking - там ему "было проще всё, ну или понятней". Какого лешего ему понадобилось лезть в индейские мультипоточные блокирующие дебри - до сих пор не понятно. Было бы хотя бы вразумительное обоснование выбора Инди - был бы тогда и стимул вдалбливать ему про синхронизацию и прочую мультипоточную требуху. А так - что о стенку горох)
-
правильная конфигурация: сервер постоянно читает запросы клиентов. получив запрос клиента, отправляет ему ответ, затем снова читает/ждет следующий запрос.
рассылка всем клиентам сообщения по инициативе сервера: сервер получает текст сообщения от администратора и ничего никуда не посылает. Запоминает его и ждет, когда клиент запросит " А нет ли для меня какого-нить сообчения?" Получив подобный запрос клиента, сервер отдаети ему сообщение прямо в обработчике команд, без всяких локлистов и прочей ерунды.
-
> без всяких локлистов и прочей ерунды
В мультипоточном сервере без lock-тряхомудии вряд ли обойтись) Другой вопрос - она нада ли автору, мультипоточность та самая .. Впрочем, он и сам не знает.
-
локлист нужен для операций по инициативе сервера. допустим что клиент у нас "событийный", а сервер "процедурный". то есть все построено задом наперед. тогда да. лочим список коннектов, засылаем клиентам мессаджи и разлочиваем. если же сервер посторить как строят его нормальные герои (ожидание запроса->обработка->посылка ответа ), то лочить ничего не надо. все происходит либю в OnExecute, либо в диспетчерах прикладных команд.
Но нах юный друг хочет чтобы и сервер и клиент были одновременно и сервером им клиентом.
-
> лочить ничего не надо
Ну как же не надо ?
> все происходит либю в OnExecute, либо в диспетчерах прикладных > команд
Все это происходит в контексте треда, обслуживающего текущий коннект. И тред этот и обслуживаемый им коннект полностью изолированы от прочих тредов сервера, обслуживающих как прочие коннекты, так и внутрикухонные нужды сервера. Все эти треды сервера так или иначе, рано или поздно обязательно пересекутся на доступе к тому или иному потоконебезопасному ресурсу, а, значит, потребуется синхронизация. Как она д.б. реализована - то ли локами, то ли синхр.сообщениями, то ли задействованием иных объектов илои способов синхронизации - другой вопрос.
-
Ну это само собой разумеется. Но я-то про Среадс.ЛокЛист говорил конкретно. Точнее про то, что он почти никогда не нужен правильному серверу.
-
> про то, что он почти никогда не нужен правильному серверу
С этим солидарен.
-
правильный сервер... я бы вобще не назвал то что мне нужно сервером. Вобщем ладно, спасибо вам за участие в теме, понял что помощи не будет
-
фигасе заявки. "помощи не будет".
-
> я бы вобще не назвал то что мне нужно сервером
Обзови его хоть горшком - как он был сервером, так он им и останется. Его задача - обслуживать (to serve) клиентов, если они не в состоянии сами себя обслужить.
> помощи не будет
Тебе уже 68 постов только и делают, что помогают, а ты все не внемлешь.
-
> если бы я писал через TServerSocket я бы не задавал таких > тупых вопросов
Глубоко в этом сомневаюсь. Были бы другие, но не менее тупые.
-
Server.Bindings.BindingByHandle(handle : cardinal)
а это что делает?
-
вот что сложного ответить на вопрос как отправить клиенту строку зная либо хендл, либо его адрес, либо его индекс подключения?)
-
что вобще сложного в том сервере который мне нужен? та же структура что и у сервера аси, получил передал сразу вот и всё...
-
получил передал сразу вот и всё...
не сразу, а только по запросу того, кому это предназначалось.
-
Вот я клиент твоей аси. И Сергей М. тоже клиент.
Я нажимаю кнопку и запрашиваю инфо о контакте Сергея М. В это время он мне шлет сообщение "Превет Медвет" Сервер его получает и тут же сразу же мне его шлет. А я в это время отправил запрос о его профиле и жду его. А в ответ мне вместо данных его профиля приходит "Превет Медвет". Я (точнее твой чудо-клиент аси) при этом в полной уверенности что: 1. Получил не сообщение, а инфу о профиле Сергея М 2. Мне не пришло текстовое сообющение от Сергея М
дальше разжевывать надо?
-
ася что ли сидит и спрашивает у сервера есть ли для неё сообщения?
вобще один товарищ посоветровал не возится с таким сервером "посредником" а связать компы не имеющие выделенных адресов через VPN. Тока я еще не совсем дочитал что это такое... так что пойду читать, мб и не нужен будет такой сервер...
-
ася что ли сидит и спрашивает у сервера есть ли для неё сообщения?
Ты лучше спроси как она вообще получает сообщения ничего не запрашивая (якобы) и ничего не читая (якобы).
-
Хотя этот вопрос лишний. Ты попробуй сначала выкрутится из ситуации, что описана у меня в [75].
Когда в ответ на запрос информации о контакте приходит не инфа о контакте, а "Превет Медвет".
-
ну а что там выкручиться, сложности никакой. например синтаксис для собщения MSG_<сообщение>, а для инфы INFO_<инфа>, и какой тут напряг? придет себе сообщение, будет оно как сообщение, а инфу по-прежнему ждем
-
> Zalm © (07.09.09 17:51) [72]
А что ты хотел видеть в кач-ве ответа на этот вопрос ?
> а это что делает?
"Это" возвращает binding-структуру с интересующим значением поля handle.
> та же структура что и у сервера аси, получил передал сразу > вот и всё
Это тебе "сервер ася" сказал ? Или ты изучил документацию ?
> вот что сложного ответить на вопрос как
А что ты хотел увидеть в кач-ве ответа на вопрос ? Код ? Он тебе не поможет, уверяю тебя. Ты нишиша в нем не поймешь. Даже если ты сдуешь его "один в один", он у тебя работать не будет.
-
> Это тебе "сервер ася" сказал ?Или ты изучил документацию > ?
ну нет, я в начале второго курса писал подобие аси... в итоге всё работало нормально. всё передавалось и принималось.
> А что ты хотел увидеть в кач-ве ответа на вопрос ?Код ?Он > тебе не поможет, уверяю тебя.Ты нишиша в нем не поймешь. > Даже если ты сдуешь его "один в один", он у тебя работать > не будет.
почему это? это голословно))) не думаю что это мне не принесет никаких результатов... так что думаю вы ошибаетесь
-
procedure TForm1.Button1Click(Sender: TObject); var List : TList; i : integer; begin try List := IdCmdTCPServer1.Contexts.LockList; for i := 0 to Pred(List.Count) do with TIdContext(List[i]) do begin if (Connection.Socket.Binding.PeerIP = '1.2.3.4') and (Connection.Socket.Binding.PeerPort = 1234) then TIdContext(List[i]).Connection.Socket.Write('привет'); end; finally IdCmdTCPServer1.Contexts.UnlockList; end; end;
-
> я .. писал ..
Я понимаю, что ты писатель, а не читатель.
> не думаю что это мне не принесет никаких результатов
Ты вообще не думаешь. Вероятно, не спрособен думать. Иначе давным бы давно реализовал кучу данных тебе подсказок.
> Медвежонок Пятачок © (07.09.09 19:00) [82]
Зря. Клиент скорее мертв. К тому он ханделЯми озабочен, а ты ему пир:порт)
-
Сергей что ж вы злой такой?)
Спасибо большое Пятачок)
-
А TidTCPServer имеет какие-то функции\процедуры для подсчета входящего\исходящего трафика? или только руками можно посчитать? Подскажите пожалуйста)
-
Тотальный подсчет трафика не предусмотрен. Однако есть события TIdTCPConnection.OnWork , TIdIOHandler.OnWork - их можно приспособить для тотального подсчета прикладного трафика.
-
аа... Спасибо Сергей
-
такая не приятная ситуация у меня наблюдается... дело такое, подключаюсь я с телефона к своему серверу, и клиент подключаю с компа.. если какое-то, именно какое-то не определенное (время не определял) время ничего не слать, то спустя "ЭТО ВРЕМЯ" если что-то написать первая команда просто где-то теряется, а если сразу же за этой командой отправить что-то то всё опять хорошо... словно эта потерянная команда оживляет сервер или клиент парный... вы знаете почему такое может быть? детального анализа еще не делал где теряется команда и куда доходит.. сначала думал спросить у вас с чем это может быть связано.. может TerminateWaitTime 5000 на сервере дает такой эффект? или надо сделать какой-то "keep alife"?
-
У тебя ошибка в программе.
-
какая может быть ошибка предположительно? как я полнял сервер работает нормально, если пара не полная, то он и через час ответит что не кому отсылать что-то, его не надо "оживлять", а вот с клиентом похоже проблема. Может время ReadTimeout поменять? там -1 стоит
-
> какая может быть ошибка предположительно?
Какая угодно. И где угодно. Но факт, что это ошибка в твоем коде.
-
если что-то написать первая команда просто где-то теряется
не где-то, а конкретно в чьем-то неучтенном ридэлэне. кто-то ждал в нем данных, а данных не было. затем кто-то послал данные, который пошли на погашение этого ридэлэна. и создалась иллюзия, что данные исчезли в черной дыре.
PS надо было слушать дядей, которые говорили что первым делом следует разработать протокол обмена.
-
Не царское это дело - разработка протокола. Быстрей бы "пАры" "окучить"
-
> Не царское это дело - разработка протокола.Быстрей бы "пАры" > "окучить"
Да Сергей, сколько можно уже, вот какой там должен быть протокол обмена? вот хоть пример предложите.
> если что-то написать первая команда просто где-то теряется
она теряется не сразу, если что-то всё время слать то всё нормально, она теряется спустя какое-то время если ничего е слать... Так что лучше ридэлен не использовать? просто рид?
-
-
это как я давно и думаю команды всякие сделать и как надо отвечать на них? у меня это есть
-
> команды всякие сделать > как надо отвечать на них?
Это у тебя хотелось бы спросить - ты же разработчик, за тебя это никто не сделает)
Пока ты не разработаешь протокол (читай - подробную схему) взаимодействия между своми клиентами и сервером, ничего путного у тебя не получится, и помочь тебе в его реализации конкретными инструментальнымим средствами невозможно при всем к тому желании)
> у меня это есть
Ну так приведи в божеский и представь здесь имеющееся у тебя, в чем проблема-то ? Великий секрет что ли
-
Ну что тут показывать-то? показывать особо нечего. При подключении к серверу надо ввести ключ, затем если ключ не верный то сразу клиент отключается от сервера, если верный то клиент шлет
Index[10] это означает что нужно ввести идентификатор, по которому составляется пара. После того как идентификатор получен сервер шлет команду srd (да, тупая, но ничего не пришло на ум другого, рашифровывается как server ready) после этой команды сервер перестает обрабатывать то что получает, а сразу кидает второму члену пары, если таковой имеется, если нет то сервер присылает команду No send вот и всё. Есть еще всякие командочки для обслуживания, типа проверить сколько клиентов щас подключено, сменить ключ, показать адрес там и тд, думаю вас это уже не интересует потому что на ход работы это не влияет уже
-
> надо ввести ключ
Что за "ключ" ? Чем "ключ" не команда ? Где описание формата этой команды ?
> если ключ не верный
Клиент сам догадывается, что ключ не верный ? Или же сервер в ответ на это возвращает нечто, информирующее клиента о валидности или невалидности "ключа" ?
> то сразу клиент отключается
А если не отключится ? Если продолжит инф.обмен ? Что делать серверу с этим "невалидным" соединением ?
> Index[10]
Это чего, строка ? Что это означает ? Почему не Index[5555555] ? И зачем числовые параметры 5555555 передавать в строковом, а не в бинарном виде ?
> нужно ввести идентификатор, по которому составляется пара
Кому "нужно" ? Что значит "ввести" ? Где и куда его "ввести" ?
> сервер шлет команду > сервер присылает команду
Ты опять за своё ?) Какая еще "команда" ? Ну сколько можно, а ? Командует клиент, а не сервер ! Сервер получает команды от клиентов (а не клиенты получают команды от сервера), обрабатывает их и возвращает клиентам результаты обработки команд, а не команды !
> Есть еще всякие командочки для обслуживания
> не интересует потому что на ход работы это не влияет уже
Это как это не влияет ?!
Каким, спрашивается, образом клиент получит результаты обработки посылаемых им "еще командочек", если ты утверждаешь, что
> после этой команды сервер перестает обрабатывать то что > получает, а сразу кидает второму члену пары, если таковой > имеется
??
Согласно этому выходит, что клиент посылает "еще командочки для обслуживания", а серверу на их исполнение уже начхать - он прямиком посылает эти "еще командочки" тому самому "второму члену пары, если таковой имеется".
Одним словом, курам на смех такой протокол)
Переделывай, доводи до ума.
-
Кстати, а зачем понадобилось участие сервера в инф.обмене между "парами" ?
Почему участники "пары" не могут или не имеют права установить соединение друг с другом напрямую (P2P = Peer To Peer), как это реализуется в ряде известных программных продуктов схожего назначения ?
Этому есть вразумительное объяснение ? Чем продиктовано такое требование - обмен только через твой сервер-посредник ?
-
> > надо ввести ключ Что за "ключ" ?Чем "ключ" не команда ? > Где описание формата этой команды ?
нет описания, ключ это строка которая указана на сервере, вот и всё.
> > если ключ не верный
> Клиент сам догадывается, что ключ > не верный ?Или же сервер в ответ на это возвращает нечто, > информирующее клиента о валидности или невалидности "ключа" > ?
ничего не возвращает, отключает сразу и всё
> > то сразу клиент отключается > А если не отключится ? Если > продолжит инф.обмен ?Что делать серверу с этим "невалидным" > соединением ?
не может быть если не отключится, сервер принудительно разрывает соединение
> > Index[10] >Это чего, строка ? Что это означает ?
означает она только что что теперь нужно вводить индекс, что ключ был введен правильный. После ввода ключа, если он подходит, сервер отсылает эту строку.
> > нужно ввести идентификатор, по которому составляется пара
>Кому > "нужно" ? Что значит "ввести" ? Где и куда его "ввести" > ?
Нужно клиенту. Ввести значит написать и отправить на сервер.
> Согласно этому выходит, что клиент посылает "еще командочки > для обслуживания", а серверу на их исполнение уже начхать > - он прямиком посылает эти "еще командочки" тому самому > "второму члену пары, если таковой имеется".
так и выходит, после того как составлена пара кроме конкретных команд сервер ничего не воспринимает, или другими словами как вы сказали ему начхать на всё что он получает. Это так потому, что серверу не нужно знать что он получает и передает. Когда сервер получает какую либо команду, он сначала проверяет нет ли такой команды из списка так сказать технических, если такой нет, то он всё что получил кидает другому клиенту, вот и вся работа сервера. Если хотите напишите свою почту, я скажу вам адрес сервера, посмотрите как всё работает.
-
> Этому есть вразумительное объяснение ? Чем продиктовано > такое требование - обмен только через твой сервер-посредник > ?
если вы знаете как можно быстрее и проще соеденить телефон и компьютер без выделенного адреса, то подскажите.
-----------
> Если хотите напишите свою почту, я скажу вам адрес сервера, > посмотрите как всё работает.
вернее я вам пришлю программу сервера, псмотрите как он работает
-
> Zalm © (16.09.09 18:26) [101]
> ключ это строка которая указана на сервере, вот и всё > ничего не возвращает, отключает сразу и всё
Значит "ключ" - это определенная в твоем протоколе команда, на которую сервер при получении не должен отвечать.
И всё.
> не может быть если не отключится, сервер принудительно разрывает > соединение
Вот это ты и должен был указать в протоколе - при получении такой-то команды сервер немедленно разрывает соединение по своей инициативе.
Какого лешего ты указываешь разрыв со стороны клиента, если дальнейшее состояние соединение от него уже не завистит, ибо в этом случае его определяет сервер ?
> Ввести значит написать
Где написать ? На бумаге ?
> Когда сервер получает какую либо команду, он сначала проверяет > нет ли такой команды из списка так сказать технических
Когда сервер получает команду, он обязан ее выполнить, если таковая предусмотрена протоколом. И не важно техническая она или гуманитарная. На то он и сервер, чтобы выполнять знакомые ему команды или игнорировать выполнение незнакомых ему команд.
Предположим, твой сервер по команде со стороковым кодом 'HELP' обязан передать клиенту некую справочную инф-цию.
Предположим, "пара" уже состоялась, и теперь твой сервер обязан, как ты говоришь, транслировать прямиком инф.поток от одного клиента "пары" другому клиенту, не вникая в содержимое потока.
Предположим, одному клиенту состоявшейся "пары" взбрело в голову послать серверу строку 'HELP', в расчете получить от сервера ту самую справочную инф-цию.
Как твой сервер должен будет понять, кому адресована эта строка ? То ли это команда 'HELP', адресованная самому серверу, то ли это один конец "пары" кричит другому концу 'HELP' ...
> я вам пришлю программу сервера, псмотрите как он работает
У меня нет ни малейшего желания глазеть на нечто лишенное вразумительного описания протокола.
> без выделенного адреса
Что значит "без выделенного" ? Кем и кому он, по-твоему, д.б. выделен ?
-
> без выделенного адреса
Адрес не может быть не выделен - он обязателен для любого устройства, взаимодействующего с другими устройствами по IP.
-
> Значит "ключ" - это определенная в твоем протоколе команда, > на которую сервер при получении не должен отвечать.
именно так))
> > Ввести значит написать > Где написать ? На бумаге ?
Что ж вы так к словам-то всегда прям цепляетесь) всё равно где ввести, написать, или там еще какие другие варианты, набить например, тут имеется ввиду что это дело, написанное, набитое, напечатанное, надо отправить потом на сервер.
> Когда сервер получает команду, он обязан ее выполнить, если > таковая предусмотрена протоколом. И не важно техническая > она или гуманитарная. На то он и сервер, чтобы выполнять > знакомые ему команды или игнорировать выполнение незнакомых > ему команд.
так и есть, только команды хелп нет и не предвидится
> Как твой сервер должен будет понять, кому адресована эта > строка ?То ли это команда 'HELP', адресованная самому серверу, > то ли это один конец "пары" кричит другому концу 'HELP' > ...
Да просто, сервер понимает всего 5 каманд, которые он не передаст дальше, эти все команды имеют такой синтаксис \<команда>\, если он находит знакомую команду, то он её выполняет, и парному клиенту уже не передает, если он не нашел то передает...
> > без выделенного адреса >Что значит "без выделенного" ?Кем > и кому он, по-твоему, д.б. выделен ?
У моего компьютера в локальной сети адрес 10,0,0,28, как вы предполагаете возможным телефону найти такой адрес среди всего интернета? Однако у нас есть сервер который (не знаю как выразить опять прицепетесь к словам) всему нашему дому обеспечивает инет, на нем и работает моя программа, в следствии чего, телефон и мой компьютер легко могут кантактировать друг с другом.
-
> Zalm © (16.09.09 22:41) [105]
> Что ж вы так к словам-то всегда прям цепляетесь
Объясняю : неразбериха в голове с терминологией - это, прежде всего, неспособность сформулировать свою задачу или проблему кратко, точно, внятно. Нет нормальной формулировки - нет и помощи в решении проблемы. Тебя это устраивает ? Думаю, вряд ли ..
> написать, или там еще какие другие варианты, набить например, > тут имеется ввиду что это дело, написанное, набитое, напечатанное, > надо отправить потом на сервер
И к чему это словоблудие ? Неужели так трудно сказать "клиент отправляет серверу идентификатор" ? Язык что ли не поворачивается ?)
> команды хелп нет и не предвидится
Ты сам-то чего к словам цепляешься ?) Какая нафих разница, есть она у тебя или нет ее ? Ну другая какая-то вместо нее найдется, которую твой сервер точно так же не будет трактовать как команду, ибо с некоторого момента, как ты говоришь, он у тебя гонит через себя транзитом весь без исключения трафик "пары" ..
> эти все команды имеют такой синтаксис \<команда>\
Пусть в твоем протоколе имеется команда со строковым значением 'Превед !'. Пусть Васе взбрендило передать Пете строку \<Превед !>\ Как твой сервер изволит поступить в этой ситуации ? Это же знакомая ему команда и он обязан ее выполнить ! А бедный Вася сидит и ждет, когда же Петя ответит на "преведствие") А Петя ни сном ни духом не ведает, что Вася его поприветствовал, ибо сервер по недомыслию взял да встрял в их интимный разговор)
> У моего компьютера в локальной сети адрес 10,0,0,28
По барабану какой он. Адрес выделен. А то что этот адрес локальный - это совсем из другой оперы.
> среди всего интернета
А где ранее по топику ты сподобился уточнить, что всю эту петрушку ты расчитываешь использовать именно в глобальной сети ? Нигде не сподобился. И как прикажешь реагировать на это ?
> Однако у нас есть сервер который (не знаю как выразить опять > прицепетесь к словам) всему нашему дому обеспечивает инет, > на нем и работает моя программа, в следствии чего, телефон > и мой компьютер легко могут кантактировать друг с другом
Т.е. свой сервер ты не планируешь использовать нигде кроме как именно в этих условиях ?
-
> телефон и мой компьютер легко могут кантактировать друг с другом
Для этого и писать-то ничего не нужно - достаточно поднять на вашем сервере-шлюзе любой готовый подходящий VPN-сервис. Тогда любой узел (по обе стороны шлюза), которому этот сервис технологически и административно доступен, будет находиться в едином маршрутизируемом адресном пространстве.
-
> Т.е. свой сервер ты не планируешь использовать нигде кроме > как именно в этих условиях ?
он именно для этих условий и предназначен, следовательно ответ будет "да, кроме этих условий нигде не планирую"
> достаточно поднять на вашем сервере-шлюзе любой готовый > подходящий VPN-сервис.
достаточно, но наш администратор сказал что VPN у нас нет и никогда не будет на сервере, почему, он внятно и не объяснил.
> А где ранее по топику ты сподобился уточнить, что всю эту > петрушку ты расчитываешь использовать именно в глобальной > сети ?Нигде не сподобился.И как прикажешь реагировать на > это ?
а какая разница? именно там и использую.
> Пусть в твоем протоколе имеется команда со строковым значением > 'Превед !'.Пусть Васе взбрендило передать Пете строку \<Превед > !>\Как твой сервер изволит поступить в этой ситуации ?
В этом случае, сервер без всяких угрызений совести передаст пете строку \<Превед !>\ потомму то команды \<Превед !>\ по протоколу он не знает, а знает команду Превед !. Если он увидит четко то что он знает, то он выполнит. Например есть команда \data\, он выполнит и не отошлет её дальше, а если написать /data/ или \data\\ то он сраже передаст их без всякого.
-
> а какая разница?
По твоему значит нет разницы ? Ну раз нет, тогда почему твои "пары" должны ходить через твой сервер ? Пусть напрямую друг к другу и ходят, ничто ведь им не мешает : адреса им выделены, а маршрутизируемы ли эти адреса в условиях глобальной сети - тебе по барабану))
> команды \<Превед !>\ по протоколу он не знает, а знает команду > Превед !
Как это не знает ? Цитирую твое же высказывание:
> команды имеют такой синтаксис \<команда>\
Чем строка \<Превед !>\ не команда Превед ! ? Синтаксис соблюден, строковый идентификатор соответствует ожтидаемому..
> Например есть команда \data\, он выполнит и не отошлет её > дальше, а если написать /data/ или \data\\ то он сраже передаст > их без всякого
Что мешает Васе отправить Пете строку \data\ ? Ничто не мешает. И Петя эту самую \data\ никогда получит, ибо сервер, по твоим же словам, распознает это сочетание последовательно идущих символов как команду.
> команды \<Превед !>\ по протоколу он не знает, а знает команду > Превед !
Опять же, Васе взбрендило послать не \<Превед !>\, а Превед ! .. Чем не команда, по твоим словам, ожидаемая сервером ?
> наш администратор сказал что VPN у нас нет и никогда не > будет на сервере, почему, он внятно и не объяснил
Зато почему-то с радостью согласился разместить на сервере совершенно сырой, абсолютно не продуманный софт)
-
> Зато почему-то с радостью согласился разместить на сервере > совершенно сырой, абсолютно не продуманный софт)
Софт отвечает всем требованиям которые я к нему предъявляю) > Что мешает Васе отправить Пете строку \data\ ?Ничто не мешает. > И Петя эту самую \data\ никогда получит, ибо сервер, по > твоим же словам, распознает это сочетание последовательно > идущих символов как команду.
Сервер не предназначем для чата) так что никто не пришлет того что не предусмотрено... Трафик между парами определен протоколом другим (клиента, и псевдо-сервера), а в этом протоколе нет команд которые равнозначны "техническим" командам сервера) Вобщем меня теперь больше интересует код, знаю у вас будет кучу плохих слов на счет моего кода, но всё же я тут для того что бы научиться)
procedure TForm1.ServerExecute(AContext: TIdContext);
var
MSG : string;
I, J : integer;
List : Tlist;
_ip : string;
_port : word;
key : string;
begin
msg:=AContext.Connection.Socket.ReadLn();
for i := 0 to Clients.Count - 1 do
begin
if ((Clients.Clients[i].SIP=AContext.Connection.Socket.Binding.PeerIP)and(Clients.C lients[i].SPort=AContext.Connection.Socket.Binding.PeerPort))or
((Clients.Clients[i].PIP=Acontext.Connection.Socket.Binding.PeerIP)and(Clients.C lients[i].PPort=AContext.Connection.Socket.Binding.PeerPort)) then
begin
if (Clients.Clients[i].SIP=AContext.Connection.Socket.Binding.PeerIP)and
(Clients.Clients[i].SPort=AContext.Connection.Socket.Binding.PeerPort) then
begin
_ip:=Clients.Clients[i].PIP;
if _ip='' then
begin
AContext.Connection.Socket.WriteLn('No send.');
exit;
end;
_port:=Clients.Clients[i].PPort;
Send(_ip,_port,msg);
exit;
end
else
begin
_ip:=Clients.Clients[i].SIP;
if _ip='' then
begin
AContext.Connection.Socket.WriteLn('No send.');
exit;
end;
_port:=Clients.Clients[i].SPort;
Send(_ip,_port,msg);
exit;
end;
end
else
begin
end;
end;
end;
Procedure Send (ip:string;port:word;str:string);
var
i : integer;
List : Tlist;
begin
try
LIst:=Form1.Server.Contexts.LockList;
for I := 0 to List.Count - 1 do
with TidContext(List[i]) do
begin
if (connection.Socket.Binding.PeerIP=ip)and(connection.Socket.Binding.PeerPort=port ) then
begin
TidCOntext(list[i]).Connection.Socket.WriteLn(str);
exit;
end;
end;
finally
Form1.Server.Contexts.UnlockList;
end;
end;
Вопросы такие, что будет если кто-то из клиентов соберется что-то отправить, в то время как УЖЕ будет работать процедура Send вызванная предыдущим клиентом?
Type
_Pack = record
SIP : string[15];
SPort : WORD;
PIP : string[15];
PPort : Word;
Index : String[10];
end;
_Clients = class
pack : _pack;
Clients : Array of _pack;
Count : integer;
end;
var
Form1: TForm1;
Clients : _Clients;
procedure TForm1.ServerConnect(AContext: TIdContext);
var
str, IP : string;
I : integer;
Port:Word;
KEY_CHECK : String;
begin
KEY_CHECK:=Acontext.Connection.Socket.Readln();
if edit1.Text<>KEY_CHECK then Acontext.Connection.Disconnect;
AContext.Connection.Socket.Writeln('Index[<=10]');
str:=Acontext.Connection.Socket.ReadLn();
if length(str)>10 then Acontext.Connection.Disconnect;
for I := 0 to Clients.Count - 1 do
begin
if Clients.Clients[i].Index=str then
begin
if Clients.Clients[i].SIP='' then
begin
Clients.Clients[i].SIP:=Acontext.Connection.Socket.Binding.PeerIP;
Clients.Clients[i].SPort:=AContext.Connection.Socket.Binding.PeerPort;
Acontext.Connection.Socket.WriteLn('srd');
exit;
end;
if Clients.Clients[i].PIP='' then
begin
Clients.Clients[i].PIP:=Acontext.Connection.Socket.Binding.PeerIP;
Clients.Clients[i].PPort:=AContext.Connection.Socket.Binding.PeerPort;
Acontext.Connection.Socket.WriteLn('srd');
exit;
end;
AContext.Connection.Disconnect;
exit;
end;
end;
inc(Clients.Count);
SetLength(Clients.Clients,Clients.Count);
Clients.Clients[Clients.Count-1].SIP:=AContext.Connection.Socket.Binding.PeerIP;
Clients.Clients[Clients.Count-1].SPort:=AContext.Connection.Socket.Binding.PeerPort;
Clients.Clients[Clients.Count-1].Index:=str;
Acontext.Connection.Socket.WriteLn('srd');
end;
procedure TForm1.ServerDisconnect(AContext: TIdContext);
var
i, j : integer;
begin
for i := 0 to Clients.Count - 1 do
begin
if (Clients.Clients[i].SIP+':'+IntToStr(Clients.Clients[i].SPort)=AContext.Connection.Socket.Binding.PeerIP+':'+IntToStr(AContext.Connection.Socket.Binding.PeerPort)) then
begin
Clients.Clients[i].SIP:='';
Clients.Clients[i].SPort:=0;
break;
end;
if (Clients.Clients[i].PIP+':'+IntToStr(Clients.Clients[i].PPort)=AContext.Connection.Socket.Binding.PeerIP+':'+IntToStr(AContext.Connection.Socket.Binding.PeerPort)) then
begin
Clients.Clients[i].PIP:='';
Clients.Clients[i].PPort:=0;
break;
end;
end;
if (clients.Clients[i].SIP='')and(clients.Clients[i].PIP='') then
begin
for j := i to clients.Count - 1 do
Clients.Clients[j]:=Clients.Clients[j+1];
dec(clients.Count);
SetLength(clients.Clients,Clients.Count);
end;
end;
Процедуры подключения и отключения клиентов используют один и тот же массив, что будет когда неск клиентов столкнутся на одном и том же массиве, в том смысле то есть что он им обоим будет нужен сразу?
-
> Процедуры подключения и отключения клиентов используют один > и тот же массив, что будет когда неск клиентов столкнутся > на одном и том же массиве, в том смысле то есть что он им > обоим будет нужен сразу?
Грабли будут. Доступ к потоконебезопасному ресурсу обязателен к синхронизации.
> что будет если кто-то из клиентов соберется что-то отправить, > в то время как УЖЕ будет работать процедура Send вызванная > предыдущим клиентом?
Этот "кто-то" застрянет на LockList до тех пор, пока предыдущий "кто-то" не вызовет UnlockList.
-
> Сервер не предназначем для чата
Фиолетово для чего он предназначен. Превед был выбран как абстрактный пример некоего инф.сообщения, которое может трактоваться неоднозначно.
> Трафик между парами определен протоколом другим
Ну и нафих это надо - месить два протокола там где место одному ?
<код команды серверу>[<параметры команды серверу>]
В <параметры команды серверу> пиши что угодно, в т.ч. команды другого протокола, ибо серверу на них начхать - он понимает и трактует только свои команды.
Например,
Команда - SendCmdToPeer Параметры: PeerID, CmdCode, CmdParams
Команда - RecvResponceFromPeer Параметры: PeerID, CmdRequestID
-
> > Процедуры подключения и отключения клиентов используют > один > и тот же массив, что будет когда неск клиентов столкнутся > > на одном и том же массиве, в том смысле то есть что он > им > обоим будет нужен сразу?Грабли будут.Доступ к потоконебезопасному > ресурсу обязателен к синхронизации.> что будет если кто- > то из клиентов соберется что-то отправить,> в то время > как УЖЕ будет работать процедура Send вызванная > предыдущим > клиентом?Этот "кто-то" застрянет на LockList до тех пор, > пока предыдущий "кто-то" не вызовет UnlockList.
и как мне всё это исправить что бы было как надо?
-
В смысле ? Программу что ли за тебя написать ?
-
нет, ну просто алгоритм скажите пожалуйста как делать
-
Алгоритм простой:
1. Войти в крит.секцию. 2. Обратиться к ресурсу. 3. Выйти из крит.секции.
-
И все-таки ты занимаешься откровенной херней. Если это учебная задача, то она еще как-то оправдана в реализации. Но тогда и гонор знайки совсем неуместен) Если же не учебная, то достаточно попросить админа пробросить порт на твой хост. На своем хосте ты волен развернуть хоть VPN, хоть черта лысого)
-
> Но тогда и гонор знайки совсем неуместен)
вот этого не понял > Алгоритм простой: > 1. Войти в крит.секцию.2. Обратиться к > ресурсу.3. Выйти из крит.секции.
Всё было бы шикарно если бы не было бы затыков. Такое у меня уже есть.
procedure TForm1.FormCreate(Sender: TObject);
begin
_Start_time:=now;
CriticalSection:=TCriticalSection.Create;
CriticalSection.Enter;
Clients:=_Clients.Create;
CriticalSection.Leave;
Server.MaxConnections:=Limits.Value;
cl_limit.Caption:=IntTOstr(limits.Value);
end;
Да вот только в других местах почему-то лаги, если обращаться через крит секцию то иногда выдает ошибки памяти или вобще потом программа не выключается нормально, только в процессах убивать если
-
> Такое у меня уже есть
Выкинь в топку. Абсолютно бестолковый код.
> в других местах почему-то лаги
У тебя ошибки в программе.
-
> MSG : string; > I, J : integer; > List : Tlist; > _ip : string; > _port : word; > key : string;
Слова плохие будут, вот здесь плохие имена, почти все, ну ладно это дело компилятора, а вот типы уже не дело компилятора - нельзя использовать тип string generic, а не fundamental - особенно для сетевых протоколов. В Инди с этим уже много дел натворили.
-
> нельзя использовать тип string generic, а не fundamental
а побольше про это слов скажете?) Сергей, прошу тыкать пальцем, где ошибки
_Pack = record
SIP : string[15];
SPort : WORD;
PIP : string[15];
PPort : Word;
Index : String[10];
end;
_Clients = class
pack : _pack;
Clients : Array of _pack;
Count : integer;
end;
Procedure Send (ip:string;port:word;str:string);
Procedure Server_clear;
var
Link_file : TEXTFILE;
RAM_file : TEXTFILE;
Form1: TForm1;
Clients : _Clients;
_null : _pack;
CriticalSection : TCriticalSection;
_Start_time : TDATETIME;
Last_ram : real;
implementation
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Server.StopListening;
APPLICATION.Terminate;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
AssignFIle(Link_file,'link.sf');
AssignFIle(RAM_file,'ram.sf');
Rewrite(link_file);
Rewrite(ram_file);
CloseFile(link_file);
CloseFile(Ram_file);
_Start_time:=now;
CriticalSection:=TCriticalSection.Create;
CriticalSection.Enter;
Clients:=_Clients.Create;
CriticalSection.Leave;
Server.MaxConnections:=Limits.Value;
cl_limit.Caption:=IntTOstr(limits.Value);
end;
procedure TForm1.limitsClick(Sender: TObject);
begin
Server.MaxConnections:=Limits.Value;
cl_limit.Caption:=IntToStr(limits.Value);
end;
procedure TForm1.logTimer(Sender: TObject);
Var
pmc:PPROCESS_MEMORY_COUNTERS;
rm : real;
state : string;
begin
state:='';
Append(ram_file);
GetMem(pmc, SizeOf(_PROCESS_MEMORY_COUNTERS));
pmc.cb:=SizeOf(_PROCESS_MEMORY_COUNTERS);
If GetProcessMemoryInfo(GetCurrentProcess(), pmc, pmc.cb) then rm:=(pmc^.WorkingSetSize)/1024/1024;
if (rm>last_ram) then
begin
state:='+'+FloatToStrF(rm-Last_ram,ffFixed,15,3);
end;
if (rm<last_ram) then
begin
state:='-'+FloatToStrF(last_ram-rm,ffFixed,15,3);
end;
if rm=last_ram then State:='0';
Last_ram:=rm;
Writeln(ram_file,DateToStr(now)+' '+TimeToStr(now)+' \ RAM: '+FloatTOStrF(rm,ffFixed,15,3)+'\ '+state);
CloseFile(ram_file);
end;
procedure TForm1.displayClick(Sender: TObject);
var
str : string;
begin
RichEdit1.Clear;
if display.ItemIndex=0 then
begin
RichEdit1.Lines.Add('not supported');
end;
if display.ItemIndex=1 then
begin
reset(ram_file);
while not(eof(ram_file)) do
begin
readln(ram_file,str);
RichEdit1.Lines.Add(str);
end;
RichEdit1.Lines.Add('---------------------'+#13+' END');
closeFIle(ram_file);
end;
end;
procedure TForm1.ServerConnect(AContext: TIdContext);
var
str, IP : string;
I : integer;
Port:Word;
KEY_CHECK : String;
begin
KEY_CHECK:=Acontext.Connection.Socket.Readln();
if edit1.Text<>KEY_CHECK then Acontext.Connection.Disconnect;
AContext.Connection.Socket.Writeln('Index[<=10]');
str:=Acontext.Connection.Socket.ReadLn();
if length(str)>10 then Acontext.Connection.Disconnect;
for I := 0 to Clients.Count - 1 do
begin
if Clients.Clients[i].Index=str then
begin
if Clients.Clients[i].SIP='' then
begin
Clients.Clients[i].SIP:=Acontext.Connection.Socket.Binding.PeerIP;
Clients.Clients[i].SPort:=AContext.Connection.Socket.Binding.PeerPort;
Acontext.Connection.Socket.WriteLn('srd');
exit;
end;
if Clients.Clients[i].PIP='' then
begin
Clients.Clients[i].PIP:=Acontext.Connection.Socket.Binding.PeerIP;
Clients.Clients[i].PPort:=AContext.Connection.Socket.Binding.PeerPort;
Acontext.Connection.Socket.WriteLn('srd');
exit;
end;
AContext.Connection.Disconnect;
exit;
end;
end;
inc(Clients.Count);
SetLength(Clients.Clients,Clients.Count);
Clients.Clients[Clients.Count-1].SIP:=AContext.Connection.Socket.Binding.PeerIP;
Clients.Clients[Clients.Count-1].SPort:=AContext.Connection.Socket.Binding.PeerPort;
Clients.Clients[Clients.Count-1].Index:=str;
Acontext.Connection.Socket.WriteLn('srd');
end;
procedure TForm1.ServerDisconnect(AContext: TIdContext);
var
i, j : integer;
begin
for i := 0 to Clients.Count - 1 do
begin
if (Clients.Clients[i].SIP+':'+IntToStr(Clients.Clients[i].SPort)=AContext.Connection.Socket.Binding.PeerIP+':'+IntToStr(AContext.Connection.Socket.Binding.PeerPort)) then
begin
Clients.Clients[i].SIP:='';
Clients.Clients[i].SPort:=0;
break;
end;
if (Clients.Clients[i].PIP+':'+IntToStr(Clients.Clients[i].PPort)=AContext.Connection.Socket.Binding.PeerIP+':'+IntToStr(AContext.Connection.Socket.Binding.PeerPort)) then
begin
Clients.Clients[i].PIP:='';
Clients.Clients[i].PPort:=0;
break;
end;
end;
if (clients.Clients[i].SIP='')and(clients.Clients[i].PIP='') then
begin
for j := i to clients.Count - 1 do
Clients.Clients[j]:=Clients.Clients[j+1];
dec(clients.Count);
SetLength(clients.Clients,Clients.Count);
end;
end;
-
Procedure Server_clear;
var
list : TList;
i : integer;
begin
try
LIst:=Form1.Server.Contexts.LockList;
for I := 0 to List.Count - 1 do
with TidContext(List[i]) do Connection.Disconnect;
finally
Form1.Server.Contexts.UnlockList;
end;
Clients.Count:=0;
SetLength(Clients.Clients,0);
end;
procedure TForm1.ServerExecute(AContext: TIdContext);
var
MSG : string;
I, J : integer;
List : Tlist;
_ip : string;
_port : word;
key : string;
begin
msg:=AContext.Connection.Socket.ReadLn();
if msg='\reset\' then
begin
Server_clear;
end;
if msg='\сhKOL\' then
begin
end;
if msg='\chKEY\' then
begin
AContext.Connection.Socket.Writeln('KEY');
key:=AContext.Connection.Socket.Readln();
if KEY<>Edit2.Text then
begin
AContext.Connection.Socket.WriteLn('ikr');
Acontext.Connection.Disconnect;
exit;
end
else
begin
AContext.Connection.Socket.WriteLn('NK');
KEY:=AContext.Connection.Socket.ReadLn();
if Length(key)>10 then
begin
AContext.Connection.Socket.WriteLn('iks');
AContext.Connection.Disconnect;
exit;
end
else
begin
Acontext.Connection.Socket.Write('oks');
Edit1.Text:=key;
exit;
end;
end;
end;
if msg='\clients\' then
begin
Acontext.Connection.Socket.WriteLn(IntToStr(Clients.Count));
exit;
end;
if msg='\exit\' then
begin
AContext.Connection.Disconnect;
exit;
end;
if msg='\data\' then
begin
for i := 0 to Clients.Count - 1 do
begin
Acontext.Connection.Socket.WriteLn('SIP: '+Clients.Clients[i].SIP);
AContext.Connection.Socket.WriteLn('SPort: '+IntToStr(Clients.Clients[i].SPort));
AContext.Connection.Socket.WriteLn('PIP: '+Clients.Clients[i].PIP);
AContext.Connection.Socket.WriteLn('PPort: '+IntToStr(Clients.Clients[i].PPort));
AContext.Connection.Socket.WriteLn('Index: '+Clients.Clients[i].Index);
end;
exit;
end;
if msg='\i\' then
begin
AContext.Connection.Socket.WriteLn(AContext.Connection.Socket.Binding.PeerIP+':'+IntToStr(AContext.Connection.Socket.Binding.PeerPort));
exit;
end;
for i := 0 to Clients.Count - 1 do
begin
if ((Clients.Clients[i].SIP=AContext.Connection.Socket.Binding.PeerIP)and(Clients.C lients[i].SPort=AContext.Connection.Socket.Binding.PeerPort))or
((Clients.Clients[i].PIP=Acontext.Connection.Socket.Binding.PeerIP)and(Clients.C lients[i].PPort=AContext.Connection.Socket.Binding.PeerPort)) then
begin
if (Clients.Clients[i].SIP=AContext.Connection.Socket.Binding.PeerIP)and
(Clients.Clients[i].SPort=AContext.Connection.Socket.Binding.PeerPort) then
begin
_ip:=Clients.Clients[i].PIP;
if _ip='' then
begin
AContext.Connection.Socket.WriteLn('No send.');
exit;
end;
_port:=Clients.Clients[i].PPort;
Send(_ip,_port,msg);
exit;
end
else
begin
_ip:=Clients.Clients[i].SIP;
if _ip='' then
begin
AContext.Connection.Socket.WriteLn('No send.');
exit;
end;
_port:=Clients.Clients[i].SPort;
Send(_ip,_port,msg);
exit;
end;
end
else
begin
end;
end;
end;
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
form2.show;
end;
procedure TForm1.SpeedButton2Click(Sender: TObject);
begin
Application.Terminate;
end;
procedure TForm1.SpeedButton3Click(Sender: TObject);
begin
Tray.Visible:=True;
Form1.Hide;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
day : integer;
pmc:PPROCESS_MEMORY_COUNTERS;
begin
cl.Caption:=IntToStr(Clients.Count*2);
Start_time.Caption:=TimeToStr(_Start_time);
if Abs(_Start_time-now)>1 then
begin
day:=Abs(Trunc(_Start_time-now));
form1.work_time.Caption:=FloatToStr(day)+' д. '+TimeToStr(_Start_time-now);
end
else form1.work_time.Caption:=TimeToStr(now-_Start_time);
GetMem(pmc, SizeOf(_PROCESS_MEMORY_COUNTERS));
pmc.cb:=SizeOf(_PROCESS_MEMORY_COUNTERS);
If GetProcessMemoryInfo(GetCurrentProcess(), pmc, pmc.cb) then
begin
ram.Caption:=FloatToStrF((pmc^.WorkingSetSize)/1024/1024,ffFixed,15,3)+' Мб';
FreeMem(pmc);
end;
end;
procedure TForm1.TrayClick(Sender: TObject);
begin
Form1.Show;
Tray.Visible:=False;
end;
Procedure Send (ip:string;port:word;str:string);
var
i : integer;
List : Tlist;
begin
try
LIst:=Form1.Server.Contexts.LockList;
for I := 0 to List.Count - 1 do
with TidContext(List[i]) do
begin
if (connection.Socket.Binding.PeerIP=ip)and(connection.Socket.Binding.PeerPort=port ) then
begin
TidCOntext(list[i]).Connection.Socket.WriteLn(str);
break;
end;
end;
finally
Form1.Server.Contexts.UnlockList;
end;
end;
-
Я ж палец сломаю, если буду в каждую тыкать : весь этот код - одна сплошная большая ошибка)
Вот скажи, ты за каким создал объект CriticalSection, если нигде кроме как в Form1.OnCreate его в последствии не используешь для защиты ресурса Clients ? И от кого ты защищаешь ресурс Clients при обработке события Form1.OnCreate, если в этот момент не существует ни единого потока кроме основного ?
-
> Я ж палец сломаю, если буду в каждую тыкать : весь этот > код - одна сплошная большая ошибка)
ну так дело никуда не сдвинется... не хорошо так..
> Вот скажи, ты за каким создал объект CriticalSection, если > нигде кроме как в Form1.OnCreate его в последствии не используешь > для защиты ресурса Clients ?
Раньше использховал, в ONConnect и OnDisconnect, но с ним вылазили ошибки, а без него всем стало хорошо xD Я попробую это исправить.
-
> так дело никуда не сдвинется
Конечно не сдвинется.. Думать-то ты по-прежнему не хочешь..
> с ним вылазили ошибки, а без него всем стало хорошо
Чего ж ты тогда продолжаешь топик и постишь код, при котором "всем стало хорошо" ?)
-
> Чего ж ты тогда продолжаешь топик и постишь код, при котором > "всем стало хорошо" ?)
)))) Так с крит секциями правильно?
procedure TForm1.ServerConnect(AContext: TIdContext);
var
str, IP : string;
I : integer;
Port:Word;
KEY_CHECK : String;
begin
KEY_CHECK:=Acontext.Connection.Socket.Readln();
if edit1.Text<>KEY_CHECK then Acontext.Connection.Disconnect;
AContext.Connection.Socket.Writeln('Index[<=10]');
str:=Acontext.Connection.Socket.ReadLn();
if length(str)>10 then Acontext.Connection.Disconnect;
CriticalSection.Enter;
for I := 0 to Clients.Count - 1 do
begin
if Clients.Clients[i].Index=str then
begin
if Clients.Clients[i].SIP='' then
begin
Clients.Clients[i].SIP:=Acontext.Connection.Socket.Binding.PeerIP;
Clients.Clients[i].SPort:=AContext.Connection.Socket.Binding.PeerPort;
Acontext.Connection.Socket.WriteLn('srd');
CriticalSection.Leave;
exit;
end;
if Clients.Clients[i].PIP='' then
begin
Clients.Clients[i].PIP:=Acontext.Connection.Socket.Binding.PeerIP;
Clients.Clients[i].PPort:=AContext.Connection.Socket.Binding.PeerPort;
Acontext.Connection.Socket.WriteLn('srd');
CriticalSection.Leave;
exit;
end;
AContext.Connection.Disconnect;
CriticalSection.Leave;
exit;
end;
end;
inc(Clients.Count);
SetLength(Clients.Clients,Clients.Count);
Clients.Clients[Clients.Count-1].SIP:=AContext.Connection.Socket.Binding.PeerIP;
Clients.Clients[Clients.Count-1].SPort:=AContext.Connection.Socket.Binding.PeerPort;
Clients.Clients[Clients.Count-1].Index:=str;
CriticalSection.Leave;
Acontext.Connection.Socket.WriteLn('srd');
end;
-
неправильно. причем неправильно не из за секций.
-
> edit1.Text
Это тоже потоконебезопасное обращение. Ты, кстати, про try..finally что-нибудь слышал ?
-
> Сергей М. (19.09.2009 15:23:08) [128]
select from insert to "Сергей М." сообщил/сообщила в новостях следующее: news:1251710046.128@delphimaster.ru... Сергей М. © (19.09.2009 15:23) [128] > edit1.Text Это тоже потоконебезопасное обращение. Ты, кстати, про try..finally что-нибудь слышал ?
-
> неправильно. причем неправильно не из за секций.
а почему не сказал из-за чего :(
Сергей, вы так и не сказали секции правильно или нет...
Про try..finally слышал, я его обычно для ошибок использую Try..Except
-
> секции правильно или нет
С учетом того, что обращение к Edit1 не защищено - нет, не правильно.
> Про try..finally слышал, я его обычно для ошибок использую > Try..Except
Что за бред ? finally - это finally, а except - это except. Две разные разницы.
-
CS.Enter; try .. обращение к потоконебезопасному ресурсу .. finally CS.Leave; end;
-
Здравствуйте, это опять я) А как убирать мертвые подключения? вернее как узнать когда оно уже не работающее? а то сервер бывает пытается отправить тому что не подключен, отправляет и никакой ошибки не пишет...(
-
Куда не пишет ? И разве он обязан куда-то что-то писать ?
-
О, Сергей опять вы) Прям рад что вы мне снова отвечаете))
А как мне тогда убирать не работающие подключения? или как можно сделать что бы сервер сам следил за тем что работатет, а что нет? Посоветуйте пожалуйста как лучше сделать
-
Детский сад продолжается? :)
> А как мне тогда убирать не работающие подключения?
Это каких таких?
-
> Dennis I. Komarov © (29.10.09 12:07) [136]
> Это каких таких?
Ну, наверно, тех, которые уборщица Тётьклава случайно оборвала орудуя шваброй)
> Zalm © (29.10.09 11:53) [135] > А как мне тогда убирать не работающие подключения?
Надо обратиться к такому подключению. При отсутствии петли подключения попытка вызова метода передачи должна привести к исключению соотв.класса.
-
> Ну, наверно, тех, которые уборщица Тётьклава случайно оборвала > орудуя шваброй)
Дома уборщица тетя Клава, а на программиста денег нету...
-
хех... детский сад\не детский... зачем вот это всё говорить надо.
-
> Zalm © (29.10.09 16:05) [139]
Ну, может совесть проснется, так не книжку какую-нить почитать, а хотя бы вопросы формулировать понятно будем...
-
вот, если отправит не работающему подключение функция должна вернуть false, однако не возвращает. Или где я не правильно написал?
Function Send(ip:string;port:word;str:string):boolean;
var
i : integer;
List : Tlist;
begin
try
LIst:=Form1.Server.Contexts.LockList;
for I := 0 to List.Count - 1 do
with TidContext(List[i]) do
begin
if (connection.Socket.Binding.PeerIP=ip)and(connection.Socket.Binding.PeerPort=port ) then
begin
try
TidContext(list[i]).Connection.Socket.WriteLn(str);
except
Result:=False;
end;
Result:=True;
break;
end;
end;
finally
Form1.Server.Contexts.UnlockList;
end;
end;
-
> except > Result:=False; > end; > Result:=True;
Сам-то понял, что ты тут творишь ?)
-
а что? прогресс на лицо ;) и логика появилась...
|