Форум: "Начинающим";
Текущий архив: 2006.09.17;
Скачать: [xml.tar.bz2];
Внизвопрос по сокетам Найти похожие ветки
← →
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;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.042 c