Форум: "Сети";
Текущий архив: 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.041 c