Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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
2-1155573235
serko
2006-08-14 20:33
2006.09.17
Сетевая база!


2-1156598583
Wiedzmin
2006-08-26 17:23
2006.09.17
Суммирование данных.Ошибка в коде?


2-1157025359
Neket
2006-08-31 15:55
2006.09.17
Скрытие программы от посторонних глаз


2-1156510613
Der Nechk@ssoff
2006-08-25 16:56
2006.09.17
Определить тип файла


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





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