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

Вниз

Как сделать для каждого пользователя подкл. к серверу свой слиент   Найти похожие ветки 

 
MegaVolt ©   (2004-11-09 17:45) [0]

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

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

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


 
Reindeer Moss Eater ©   (2004-11-09 18:18) [1]

Такую связку надо делать почитав книжки.


 
MegaVolt ©   (2004-11-10 09:12) [2]

Согласен всё нужно делать почитав книжки. Я ознакомился со всеми доступными материалами как на бумаге так и в инете. И в основном рассмотрены вопросы работы приложений которые имеют одностороннюю связь с сетью. Вопросы же приложений которые служат для обработки трафика практически нет. Если бы выходное приложжение позволяло работать через одно соединение проблемы бы не было. А оно требует от каждого клиента своё соединение. Т.е. я должен поддерживать много входных и много выходных соединений и осуществлять передачу инфы между ними. У меня основное затруднение вызывает создание и удаление этих соеднений. Мне необходим только набросок принципа работы. А точнее вопросы как создать выходное соединение пока входное соединение ещё не успело потерять входную информацию т.к. ServerSocket высылает подтверждение пользователю на установление соединения до того как создан сокет обрабатывающий это соединение.

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


 
Reindeer Moss Eater ©   (2004-11-10 09:34) [3]

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

Назови один пример найденного тобой приложения имеющего "одностороннюю связь с сетью"


 
Виктор ©   (2004-11-10 09:49) [4]

MegaVolt ©   (10.11.04 09:12) [2]
Выкладывай на обозрение, меня этот вопрос тоже интересует, имеется своё мнение по поводу создания сокетов.


 
Reindeer Moss Eater ©   (2004-11-10 09:52) [5]

Мне удалось создать работающий код который в тестовых условиях с парой клиентов успешно работал. Однако при нагрузке в 100 клиентов падал.

Круто.
Ты попробуй этот код выдели жирным и красным.
Может он станет мощнее и вытянет еще пару клиентов.


 
MegaVolt ©   (2004-11-10 10:04) [6]

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.


 
Reindeer Moss Eater ©   (2004-11-10 10:24) [7]

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

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


 
MegaVolt ©   (2004-11-10 10:31) [8]

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


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

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

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


 
Verg ©   (2004-11-10 10:53) [10]

[6] MegaVolt ©   (10.11.04 10:04)

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

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

Например, TIdMappedPortTCP.


 
MegaVolt ©   (2004-11-10 10:54) [11]

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

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

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


 
MegaVolt ©   (2004-11-10 10:56) [12]

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


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

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


 
MegaVolt ©   (2004-11-10 11:03) [14]

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


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

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

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

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


 
Verg ©   (2004-11-10 11:12) [16]


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


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


 
MegaVolt ©   (2004-11-10 11:15) [17]

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


 
Reindeer Moss Eater ©   (2004-11-10 11:17) [18]

Тады Verg[10]


 
Digitman ©   (2004-11-10 11:19) [19]


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


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

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

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


 
MegaVolt ©   (2004-11-10 11:24) [20]

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

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


 
Digitman ©   (2004-11-10 11:54) [21]


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


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

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


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


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

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


 
MegaVolt ©   (2004-11-10 12:09) [22]

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


 
MegaVolt ©   (2004-11-10 15:29) [23]

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


 
Knight ©   (2004-11-10 19:25) [24]

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

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

подойдёт?


 
MegaVolt ©   (2004-11-11 09:11) [25]

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



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

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

Наверх





Память: 0.55 MB
Время: 0.044 c
6-1099864447
Роман
2004-11-08 00:54
2005.01.30
Траффик и дозвон.


3-1103996779
Russko
2004-12-25 20:46
2005.01.30
InterBase не хочет сохранять изменения (


3-1104138100
intaari
2004-12-27 12:01
2005.01.30
Возможно ли редактирование записей полученных по запросу


14-1105492871
aus
2005-01-12 04:21
2005.01.30
Антивирус


1-1106046599
Ser_max
2005-01-18 14:09
2005.01.30
свойстваTchart





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