Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.09.17;
Скачать: CL | DM;

Вниз

вопрос по сокетам   Найти похожие ветки 

 
Ezorcist   (2006-08-31 08:36) [0]

var
 Form1: TForm1;
 S:TServerClientWinSocket;

implementation

{$R *.dfm}

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
 Socket: TCustomWinSocket);
begin
S:=TServerClientWinSocket(Socket);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
S.SendText("bla-bla")
end;


Нормально создать такую переменную для упрощения посылки данных на конкретное соединение? (т.е. если соединений много, то при посылки не отыскивать нужный сокет по сочетанию IP+Port а выбрать, например, из массива?)


 
Сергей М. ©   (2006-08-31 09:01) [1]


> Нормально создать такую переменную для упрощения посылки
> данных на конкретное соединение?


Это зависит от логики взаимодействия сервера и его клиентов.

Если я правильно понимаю, тебе в некий произвольный момент времени (в дан.случае - момент нажатия кнопки) нужно ответить только тем клиентам, которые на этот момент прислали некие запросы ?


 
Ezorcist   (2006-08-31 10:18) [2]

Программа - чат.
Кто прислал собщение я определяю по комбинации IP+Port, которая заноситься в массив с данными о пользователях. Потом надо послать сообщение пользователю зная его IP + Port. Тут нужен перебор, так?

Ну вот я и подумал что быстрее бы было заносить в массив не IP+Port а ссылку на сокет, который отвечает за соединение с конкретным пользователем. Или я что неправильно понимаю... ???


 
Сергей М. ©   (2006-08-31 10:34) [3]

Ну а выбор конкретного элемента массива по каким критериям собираешься осуществлять ? Ведь в массиве этом - "безликие" ссылки ..

В чатах, как правило, реализованы 3 режима:

1. бродкаст - сообщение пользователя рассылается всем без исключения пользователям.

2. фильтр-бродкаст - сообщение пользователя рассылается только тем пользователям, у которых приславший сообщение пользователь не фигурирует в игнор-списке

3. приват - сообщение пользователя пересылается только конкретному выбранному пользователю.

Режим 1 вообще не требует никакого перебора.

Режим 2 безусловно требует перебор списков.

Режим 3 требует перебор, если приват не реализован как сессия.

Ты о каких режимах сейчас говоришь ?


 
Ezorcist   (2006-08-31 11:06) [4]

Хм... значит подробнее...

все пользователи подключаются к одному порту и к одному TServerSocket (правильно ли это?). А потом они могут войти\выйти в определенный канал (которых есть множество.) При этом ID пользователя добавляется в список пользователей канала, а ID канала в список каналов конкретного пользователя, т.е. 2 связаннх списка в которых я и увяз... (( А вот если бы у канала был список со ссылками на сокеты, то он бы мог просто отослать всем сокетам одно и тоже сообщение (для режима 1).

А разве они безлики? т.е. там разве нет Remote IP+Port, по которому можно осуществить поиск.


 
Сергей М. ©   (2006-08-31 11:19) [5]


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


Ну так и веди такой список для каждого канала !
Для каждого канала организуй обычный TList, в него при "подписке" клиента на канал добавляй как новый элемент списка ссылку на структуру, ассоциирующую ID клиента с его TServerClientWinSocket, при "отписке" удаляй соотв.элемент списка.


> по которому можно осуществить поиск


Мне не понятно, что ты там искать еще собрался..

Когда клиент "подписался" на канал, св-ву TServerClientWinSocket.Data присваивается ссылка на TList этого канала, при "отписке" это св-во соответственно обнуляется.
При получении сообщения от клиента для всех пользователей выбранного им канала берется TList из св-ва TServerClientWinSocket.Data, в цикле перебираются все его элементы, из каждого элемента из структуры извлекается ссылка на соотв.TServerClientWinSocket и вызывается его Send-метод.


 
Ezorcist   (2006-08-31 11:30) [6]


> Когда клиент "подписался" на канал, св-ву TServerClientWinSocket.
> Data присваивается ссылка на TList этого канала,


Так вроде сокет один а каналов много...


 
Сергей М. ©   (2006-08-31 11:34) [7]

И ?

У тебя что, клиент должен иметь одновременную подписку на более чем один канал ?


 
Ezorcist   (2006-08-31 11:57) [8]

именно


 
Сергей М. ©   (2006-08-31 12:08) [9]

Ну тогда храни в св-ве Data ссылку на TList - список каналов (список списков), на которые подписан клиент


 
Ezorcist   (2006-08-31 12:19) [10]

угу понятно, еше вопрос: когда данные приходят на до узнать от кого. Раньше я писал так:

for i:= 0 to 5 do
if (info[i].ip=socket.remoteaddress) and (info[i].port=socket.remoteport) then begin
showmessage("# пользователя = "+inttostr(i));
break;
end;

(массив для примера) а теперь можнозаменить 2ую строку на
if info[i].sock=TServerClientWinSocket(Socket) then begin

Но мне почему - то кажется что первый способ будет быстрее.. так ли это? (или способ вообще в корне неверен?)


 
Сергей М. ©   (2006-08-31 12:56) [11]


> когда данные приходят на до узнать от кого


Не вижу никакого смысла использовать для идентификации IP+Port и отдельный массив.

Заведи структуры а-ля

PChannelInfo = ^TChannelInfo;
TChannelInfo = packed record
 ChannelName: String; //уникальное имя канала
 Users: TList; //список ссылок на объекты TServerClientWinSocket пользователей, подписанных на канал
end;

PUserInfo = ^TUserInfo
TUserInfo = packed record
 NikName: String; //уникальный ник пользователя
 Subscriptions: TList; //список ссылок на структуры TChannelInfo, описывающие каналы, на которые подписан пользователь
end;

При коннекте юзера создай структуру типа TUserInfo и запиши ссылку на нее в св-во Socket.Data (при дисконнекте соотв-но уничтожай структуры)

При авторизации пользователя записывай его ник в поле PUserInfo(Socket.Data).NikName

При создании канала создай структуры типа TChannelInfo, заполни в структуре поле имени канала ChannelName и запиши ссылку на структуру в список каналов (при  уничтодении канала уничтожай соотв.структуру и удали соотв.элемент списка каналов)

При подписке польз-ля на канал добавь ссылку на его ServerClientWinSocket в список Users этого канала, а так же добавь ссылку на структуру TChannelInfo в список Subscriptions (при отписке соответственно удаляй ранее добавленные ссылки из списков Users и Subscriptions)

При получении сообщения от пользователя:

- из PUserInfo(Socket.Data).NikName берешь ник пользователя
- из PUserInfo(Socket.Data).Subscriptions берешь список каналов, на которые пользователь подписан
- ищешь в этом списке ссылку на структуру TChannelInfo, описывающую канал, которому адресовано сообщение
- берешь из полученной структуры список Users и в цикле выполняешь Send-метод для каждого юзера канала, исключая себя если необходимо.


 
Ezorcist   (2006-08-31 15:42) [12]

Большое спасибо за грамотный ответ! Очень помогло!


 
Сергей М. ©   (2006-08-31 15:53) [13]

Надо же)...

Никогда в жизни не занимался этой чат-хренью, а большую спасибу таки заработал при этом)



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

Текущий архив: 2006.09.17;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.038 c
15-1156359146
Petr V. Abramov
2006-08-23 22:52
2006.09.17
Про обчество патредблеия и старых пердунов


2-1156777707
иван8511
2006-08-28 19:08
2006.09.17
Фукция асемблера?


8-1141368979
sergey2006
2006-03-03 09:56
2006.09.17
Использование directshow


2-1156910249
demonn1112
2006-08-30 07:57
2006.09.17
treeview


3-1152612237
chizra
2006-07-11 14:03
2006.09.17
Как шифровать данные в базе данных на лету?