Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как сделать для каждого пользователя подкл. к серверу свой слиент [D5, Win95/98, Win2k, WinXP]


Страницы:   1 2

MegaVolt ©   (2004-11-09 17:45:00) 

К сожалению текст того что я наваял удалили неизвесно за что :(
По нему было бы очень удобно критиковать.

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

Как нужно делать такую связку?


MegaVolt   (2004-11-11 09:11:00) [1]

KnightСпасибо я видел эту статью. Но TIdMappedPortTCP делает всё то что мне нужно :)


Knight   (2004-11-10 19:25:00) [2]

Помню, что где-то, что-то подобное видел... вот нашёл...

http://www.codersclub.net/articles/339.html

подойдёт?


MegaVolt   (2004-11-10 15:29:00) [3]

Извиняюсь но где находится TIdServerIntercept ?  Что то на закладках я его найти не могу :(


MegaVolt   (2004-11-10 12:09:00) [4]

Почитал про TIdMappedPortTCP. Похоже именно то что нужно :):) Качаю Indy :) Спасибо за помощь :)


Digitman   (2004-11-10 11:54:00) [5]


> MegaVolt ©   (10.11.04 11:24) [20]


я не вникал в подробности того, что и как ты там собрался "прослушивать" - это совершенно из другой оперы, нежели организация собственно инф.обмена с использованием классов TServerSocket/TClientSocket, и эта "другая опера" не имеет никакого отношения к вопросу о "правильности" создания объектов упомянутых классов

касаемо же вопроса


> как правильно создавать новый ClientSocket ?


ответ до смешного прост и банален - поскольку класс TClientSocket есть наследник класса TComponent, создание объекта этого класса сводится к успешному выполнению строчки

SomeClientSocket := TClientSocket.Create(компонент-владелец или nil, если оной не нужен по логике);


MegaVolt   (2004-11-10 11:24:00) [6]

Reindeer Moss EaterА он может MegaVolt [12]

DigitmanСогласен. Похоже так действительно хуже :( Переименовать? И выложить заново?
Можешь просто набросать как правильно создавать новый ClientSocket? Для одного я делал так Вначале создаётся ClientSocket затем если удалось включаю прослущивание в ServerSocket. Всё класненько. А вот как красиво создавать слиентов при множесте водключившихся я не в курсе. Подскажешь алгоритм хотф бы набросок?


Digitman   (2004-11-10 11:19:00) [7]


> MegaVolt ©   (10.11.04 10:04) [6]


слушай, ты этими терминами Chat/User и используемыми соответственно идентификаторами ChatSocket/UserSocket привнес в алгоритм такую путаницу, что и сам кажется запутался окончательно и у других в нем разбираться вряд ли желание возникнет.

Раз ты взял на вооружение концепцию и технологию организации инф.обмена распределенных сетевых приложений с использованием выделенного сервера, то будь уж так любезен и придерживаться терминов Server/Client и соотв-но имен используемых идентификаторов ServerSocket/ClientSocket

Чат там это или не чат - по барабану, все это просто инф-й обмен по некоему прикладному протоколу.
А уж если без слова "чат" работа по грамотной организации транспортного алгоритма у тебя никак не клеится, пользуй терминологию ChatServer/ChatClient и соотв-но имена используемых идентификаторов ChatServerSocket/ChatClientSocket


Reindeer Moss Eater   (2004-11-10 11:17:00) [8]

Тады Verg[10]


MegaVolt   (2004-11-10 11:15:00) [9]

Reindeer Moss Eater:) Мне нужно создать позрачный экран закрывающий дыры в другой программе. Т.е. пользователи коннектятся например на порт 123. Я получаю их данные обрабатываю их и посылаю дырявому приложению на порт 456 сообщения от него обрабатываю и посылаю обратно пользоваетелям от имени порта 123. Т.е. пользователь считает что работает с программой а на самом деле работает с моим фильтром. Количество подключений к дырявой программе должно быть равно количеству соединений от клиентов. Т.е. Слиент-моя прога порт 123 например 100 соединений. Моя прога-дырявая прога порт 456 тоже 100 соединений.


Verg   (2004-11-10 11:12:00) [10]


> [15] Reindeer Moss Eater ©   (10.11.04 11:06)


Проксик ему надо по принципу TCP-Mapping Service, чтобы через себя прокачивать всю информацию по каждому соединению.


Reindeer Moss Eater   (2004-11-10 11:06:00) [11]

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

Что такое "входное и выходное двунаправленное подключение" я себе слабо представляю.

Подключение к кому/к чему?


MegaVolt   (2004-11-10 11:03:00) [12]

Reindeer Moss EaterОн позволяет для кадого пользователя создать автоматом входное и выходное двунаправленное подключение? Или это просто аналог TSlientServer


Reindeer Moss Eater   (2004-11-10 10:57:00) [13]

Зачем TIdMappedPortTCP если TidTCPServer - это все что нужно?


MegaVolt   (2004-11-10 10:56:00) [14]

Vergа что он может? Он позволит мне встроить в него свой обработчик пакетов? Чтобы я мог отсеивать и анализировать пакеты с информацией?


MegaVolt   (2004-11-10 10:54:00) [15]

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

Слабым вопросом у себя считаю именно создание и удаление сокетов.

В часности созданный слушающий соукет принимает запрос на подключение и сам же устанавливает соединение. Т.е. информацию о подключении я получаю в тот же момент когда и клиент. Клиент же в это время уже начинает передавать информация а у меня ещё не создан сокет для обработки этой информации. И как разрулить этот вопрос я не очень представляю :( Если бы была возможность задержать отправку подтверждение соединения пользователю то проблема была бы решено но как это сделать я не знаю :(


Verg   (2004-11-10 10:53:00) [16]

[6] MegaVolt ©   (10.11.04 10:04)

Да не мучайся ты так-то уж....

Возьми готовый TCP маппер. Разберись с сним.

Например, TIdMappedPortTCP.


Виктор   (2004-11-10 10:43:00) [17]

Вообщем реального кода у меня нет.
Но писать я бы сделал так:
1. Сервер-который слушает всех кто хочет подконнектися.
2. Менеджер подключений который берет на себя право решать
что делать с рвущимся в коннект и что делать с уже имеющимся
коннектами.
3. Собственно коннект в виде потока который выполняет какие-то
действия с получаемой информацией.

А твой код трудно переварить в таком количестве.
В чем у тебя проблема конкретно?
Если он работает, то что тебя не устраивает?


MegaVolt   (2004-11-10 10:31:00) [18]

Почему ни кто не просил? Например Виктор попросил.


Reindeer Moss Eater   (2004-11-10 10:24:00) [19]

Односторонний - это идущий в одну сторону.
В автошколу поступи и узнай там что такое одностороннее движение.

PS. Код приложения постить никто не просил.


MegaVolt   (2004-11-10 10:04:00) [20]

Reindeer Moss EaterПримером односторонней связи с сетью является например дельфящный чат. Односторонний это в смысле того что поток информации приходит и уходит через одно соединение. Например ведро это односторонее соединение т.к. в него можно наливать и выливать. А труба уже двухсторонее. А мне нужно сделать не просто трубу а связку труб.

На счёт жирным и красным извини не понял :( Я написал то что я смог добится самостоятеьно. Понял что моих знаний на это не хватает и решил обратится за помощью.

Вот код может так станет проще разговаривать.

TUser = class
 public
   Nick: string;
   SocketUser:TServerClientWinSocket;
   SocketChat:TClientSocket;
   Connect:boolean;
   IP: string;
   From:string;
   MAC:String;
end;

var
 Form1: TForm1;
 //Users: Tusers;
 ListUser:TList;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var
 ini:TIniFile;
begin
 ListUser:=TList.Create;
 Ini:=TIniFile.Create(ExtractFilePath(ParamStr(0))+'iFireWall.ini');
 ChatSocket.Address:=Ini.ReadString('Config','ChatAddr','');
 if ChatSocket.Address=''
   then
     begin
       ShowMessage('Пропишите настройки инишки');
       Exit;
     end;
 ChatSocket.Port:=Ini.ReadInteger('Config','ChatPort',0);
 if ChatSocket.Port=0
   then
     begin
       ShowMessage('Пропишите настройки инишки');
       Exit;
     end;
 UserSocket.Port:=Ini.ReadInteger('Config','UserPort',0);
 if UserSocket.Port=0
   then
     begin
       ShowMessage('Пропишите настройки инишки');
       Exit;
     end;
 ChatSocket.Active:=true;
end;

procedure TForm1.ChatSocketError(Sender: TObject;
 Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
 var ErrorCode: Integer);
begin
 ErrorCode := 0;
end;

procedure TForm1.ChatSocketConnect(Sender: TObject;
 Socket: TCustomWinSocket);
begin
 if GetServerSocket(TClientSocket(Socket))=-1
   then
     begin
       RichEdit1.Lines.Add('Соединение с сервером установлено');
       UserSocket.Active:=true;
       RichEdit1.Lines.Add('Включено прослушивание входного порта');
     end;
end;

procedure TForm1.ChatSocketDisconnect(Sender: TObject;
 Socket: TCustomWinSocket);
begin
 UserSocket.Active:=false;
 RichEdit1.Lines.Add('Сервер чата недоступен');
end;

procedure TForm1.UserSocketClientError(Sender: TObject;
 Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
 var ErrorCode: Integer);
begin
 ErrorCode := 0;
end;

procedure TForm1.UserSocketClientDisconnect(Sender: TObject;
 Socket: TCustomWinSocket);
var
 ind:integer;
begin
 ind:=GetChatSocket(Socket);
 if ind<>-1 then TUser(ListUser[Ind]).SocketChat.Destroy;
 ListUser.Delete(Ind);
end;

function TForm1.GetChatSocket(Socket:TCustomWinSocket):integer;
var
 i:integer;
begin
 Result:=-1;
 for i:=0 to ListUser.Count-1 do
   begin
     if integer(TUser(ListUser[i]).SocketUser)=integer(Socket)
       then
         begin
           Result:=i;
           Exit;
         end;
   end;
end;

function TForm1.GetServerSocket(Socket:TClientSocket):integer;
var
 i:integer;
begin
 Result:=-1;
 for i:=0 to ListUser.Count-1 do
   begin
     if integer(TUser(ListUser[i]).SocketChat.Socket)=integer(Socket)
       then
         begin
           Result:=i;
           Exit;
         end;
   end;
end;

procedure TForm1.UserSocketClientRead(Sender: TObject;
 Socket: TCustomWinSocket);
var
 Buf: array[1..65536] of char;
 Len: integer;
 Ind:integer;
begin
 // Организуем поток от ползователей к чату
 Len := socket.ReceiveBuf(Buf,65536);
 Ind:=GetChatSocket(Socket);
 if Ind<>-1 then TUser(ListUser[Ind]).SocketChat.Socket.SendBuf(buf,len);
end;

procedure TForm1.ChatSocketRead(Sender: TObject; Socket: TCustomWinSocket);
var
 Buf: array[1..65536] of char;
 Len: integer;
 Ind:integer;
begin
 // Организуем поток от чата к пользоваетлям.
 Len := socket.ReceiveBuf(Buf,65536);
 Ind:=GetServerSocket(TClientSocket(Socket));
 if Ind<>-1 then TUser(ListUser[Ind]).SocketUser.SendBuf(Buf,Len);
end;

procedure TForm1.UserSocketGetSocket(Sender: TObject; Socket: Integer;
 var ClientSocket: TServerClientWinSocket);
var
 ind:integer;
begin
 ind:=ListUser.Add(TUser.Create);
 with TUser(ListUser[ind]) do
   begin
     Nick:='';
     SocketUser:=nil;
     SocketChat:=nil;
     Connect:=false;
     From:='';
     MAC:='';
   end;
 TUser(ListUser[ind]).SocketChat:=TClientSocket.Create(Form1);
 with TUser(ListUser[ind]).SocketChat do
   begin
     Address:=ChatSocket.Address;
     Port:=ChatSocket.Port;
     OnConnect:=ChatSocketConnect;
     OnDisconnect:=ChatSocketDisconnect;
     OnError:=ChatSocketError;
     OnRead:=ChatSocketRead;
     Active:=true;
   end;
 ClientSocket:=TServerClientWinSocket.Create(TSocket(Socket),TServerWinSocket(Sender));
 TUser(ListUser[ind]).SocketUser:=ClientSocket;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 ListUser.Destroy;
end;

{ converts numerical MAC-address to ww-xx-yy-zz string }
function MacAddr2Str( MacAddr: TMacAddress; Size: integer ): string;
var I: integer;
begin
 if Size = 0 then Result := '00-00-00-00-00-00'
 else begin
   Result := '';
   for i := 1 to Size do Result := Result + IntToHex( MacAddr[i], 2 ) + '-';
   Delete( Result, Length( Result ), 1 );
 end
end;

function GetMAC(IP:PChar):string;      // Получение MAC-адреса сетевого компьютера
const Data  : string = 'Test';
var   UDP_in    : TSockAddrIn;
     pBuf      : PChar;
     TableSize : DWORD;
     Error     : DWORD;
     NumEntries: DWORD;
     IpNetRow  : TMibIpNetRow;
     I         : Integer;
     MAC       : string;
     UDP_Socket:TSocket;
     WSA_Data  : TWSAData;
begin
  MAC:='00-00-00-00-00-00';
  TableSize:=0;
  Error:=GetIpNetTable(PTMibIpNetTable(pBuf),@TableSize,True);    // first call: get memsize needed
  if Error <> ERROR_NO_DATA
    then
      begin
        GetMem(pBuf,TableSize);
        Error:=GetIpNetTable(PTMibIpNetTable(pBuf),@TableSize,True); // get table pointer
        if Error = NO_ERROR
          then
            begin
              NumEntries:=PTMibIpNetTable(pBuf)^.dwNumEntries;
              if NumEntries > 0
                then
                  begin
                    inc(pBuf,SizeOf(NumEntries));
                    for I:=1 to NumEntries do
                      begin
                        IpNetRow:=PTMibIpNetRow(pBuf)^;
                        with IpNetRow do
                          if (dwAddr = inet_addr(IP))and(dwType<>2)
                            then MAC:=MacAddr2Str(bPhysAddr,dwPhysAddrLen);
                          inc(pBuf,SizeOf(IpNetRow));
                      end;
                    dec(pBuf,SizeOf(DWORD)+NumEntries*SizeOf(IpNetRow));
                  end;
            end;
        FreeMem(pBuf);
      end;
  Result:=MAC;
end;

procedure TForm1.UserSocketAccept(Sender: TObject;
 Socket: TCustomWinSocket);
var
 ind:integer;
begin
 ind:=GetChatSocket(Socket);
 if Ind<>-1
   then
     begin
       TUser(ListUser[ind]).IP:=Socket.RemoteAddress;
       TUser(ListUser[ind]).Mac:=GetMAC(PChar(Socket.RemoteAddress));
     end;
end;

end.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо