Вопрос по теме TServerSocket
Вопрос как я посмотрел по поиску обсуждался но решение было написано не по моей бяде, и на гугле нет ответа.
У меня создан Сервер и созданы клиенты,
но при подключение к серверу более обного клиента возникает проблема
первый подключившийся клиент получает индекс подключения 0, то есть
ServerSocket1->Socket->connections[o]
Второй клиент получает индекс 1 и т.д.
Вопрос в том как мне отправлять к примеру текст, конкретному клиенту.
Как вы вообще храните информацию о клиенте? Нельзя чтоли сделать массив (список) с экземплярами класса "TMyClient"? Массив представляет собой информацию обо всех клиентах, а в классе кроме прочего (например, ИД клиента в БД), хранить ссылку на соединение (или хотябы номер его). А добавлять в список клиента при его подключении.
А уж как отправить текст клиенту, зная соединение...
И разумеется, что "по поиску" и "на гугле" нет ответов - это настолько банально и понятно, что не стоит даже обсуждать.
P.S. А можно каждому клиенту назначить индекс покдлючения к серверу. Чтоб каждый клиент всегда подключался по одному и то муже индексу, а не так кто первый успел тот и к примеру на нулевом индексе.)))
Пример(аж не поленился):
Массив[2] Клиенты;
Событие Подключен(Информация, н_соединения)
{
Определяем что за клиент (номер_клиента)
Клиенты[номер_клиента].соединение = н_соединения;
Клиенты[номер_клиента].Активен = Да;
}
Событие Отключение(Информация, н_соединения)
{
Находим номер_клиента с Клиенты[номер_клиента].Соединение=н_соединения и
Клиенты[номер_клиента].Соединение=-1
Клиенты[номер_клиента].Активен= Нет
}
Функция ОтправитьСообщение(Текст, номер_клиента)
{
Если Клиенты[номер_клиента].Активен То
Через сокет через соединение Клиенты[номер_клиента].Соединение отправляем текст
Иначе
Ошибка!
}
Все равно не вижу проблемы. Зачем настолько жестко привязываться к индексу соединения. Просто считайте, что пока клиент подключен - индекс валиден, как только отключается (вы получите OnClientDisconnect или OnClientError) индекс становится невалидным и вы просто "забываете" о существовании этого клиента.
К примеру как вы сказали номер клиента, этот номер должен быть прописан в клиенте или при подключение например текстом отправляет свой номер?
Немного недопонимаю...:o
Вернее у меня есть список с номерами клиентов, то есть сервер скажем может проверять тот или не тот клиент, а самих клиентов я как проверить смогу, ведь у них ничего при подключение не изменяется.
То есть они идентичны друг другу.
К примеру как вы сказали номер клиента, этот номер должен быть прописан в клиенте или при подключение например текстом отправляет свой номер?
Немного недопонимаю...:o
Нет, ну уж извините, чем у вас клиенты отличаются я понятия не имею! Может быть бубликами? А может ФИО? А может mac-адрес? Откуда на форуме могут знать, как идентифицировать ваших клиентоф.
Пфффф.... пар выпустил...
Процедура идентификации клиента по передаваемым им известным ему данным называется аутентификация. Также ее иногда ставят в ряд с авторизацией. По ссылкам найдете объяснение что есть что и как это делают.
при запуске клиент программно определяет IP-адрес клиента, к примеру
10.0.4.1 после чего мы отсеиваем, а можем и не отсеивать так даж лучше
получаем идентификационный код клиента.
Я просто немогу немного понять клиент должен отправить на сервер текст
с номером индентификационным кодом, или как то подругому.
Но фишка то в чем:
К примеру клиент подключается к серверу, и отправляет текст с кодом идентификации 10.0.4.1 , затем сервер это понятно получает и сверяет соединение, но мне непонятно как на сервере сохранить индекс именно этого клиента, какой командой можно получить индекс именно этого клинта, ведь для отправки текста тому же клиенту мы должны будем указать номер индекса. то есть
ServerSocket1->socket->Connections[н_индекса]->SendText;
вот именно н_индекса как запихать в переменную?
Естественно чтобы потом использовать для передачи информации именно этому клиенту в текущей сессии.
TCustomWinSocket *Socket)
{
for(int i=0;i<ssServer->Socket->ActiveConnections;i++){
if(ssServer->Socket->Connections==Socket){
Command = ssServer->Socket->Connections->ReceiveText();
Station = Command.SubString(Command.LastDelimiter("#")+1,Command.Length());
ConnectionList->Add(Station);
ssServer->Socket->Connections[ConnectionList->IndexOf(Station)]->SendText("Connected");
mmLog->Lines->Add(DateTimeToStr(Now())+"\t���������� ������ -\t "+Station);
mmLog->Lines->Add(DateTimeToStr(Now())+"\t����� �������� -\t "+IntToStr(ConnectionList->Count));
}
}
}
делается так.
На лишние не обращай внимание - это просто кусок кода. А это чтение команд клиента:
TCustomWinSocket *Socket)
{
AnsiString TempCommand;
for(int i=0;i< ssServer->Socket->ActiveConnections;i++){
if(ssServer->Socket->Connections==Socket){
Command = ssServer->Socket->Connections->ReceiveText();
Station = Command.SubString(Command.LastDelimiter("#")+1,Command.Length());
Command = Command.Delete(Command.LastDelimiter("#"),Command.Length());
TempCommand = Command.SubString(1,Command.LastDelimiter("#")-1);
mmLog->Lines->Add(DateTimeToStr(Now())+"\t�������� ���������\t"+Command+"\t�������\t"+Station);
if(TempCommand == "Send"){
Filename = edInStation->Text+"\\"+Command.SubString(Command.Pos("#")+1,Command.Length());
acSendFiles->Execute();
}
else if(TempCommand == "Receive"){
Filename = edOutStation->Text+"\\"+Station;
acReceivFiles->Execute();
}
else if(TempCommand == "Connect"){
}
}
}
}
Код писался крайне давно и вытащен из какогото древнего бекапа - вполне может содержать ошибки и неудачные решения.
Я просто немогу немного понять клиент должен отправить на сервер текст
с номером индентификационным кодом, или как то подругому.
Но фишка то в чем:
К примеру клиент подключается к серверу, и отправляет текст с кодом идентификации 10.0.4.1 , затем сервер это понятно получает и сверяет соединение
прочти основы сетевого программирования - откроешь для себе много нового. Клиенту не нужно отправлять строку с идентификатором.
Kot_
Я бы не рекомендовал использовать TServerSocket. Глюкавый.
А чем лучше воспользоваться?
Еще проблема с сокетами в том, что ситуация:
На сервер подключилось 3 клиента.
к примеру по очереди:
Клиент1 - 0(индекс)
Клиент2 - 1(индекс)
Клиент3 - 2(индекс)
При коннекте всех трех клиентов индексы мы запомнили, но к примеру отключается Клиент1, вместо него подключается Клиент4,и становится вообще бордак:confused:
Клиент2 - 0(индекс)
Клиент3 - 1(индекс)
Клиент4 - 2(индекс)
И в итоге если у нас сохранено что клиент2 подключен к 1(индексу) , мы начинаем ему передавать текст или поток, то этот текст или поток получит клиент3. Это не есть хорошо. Какойнибудь пользователь подключисля и вместо того чтобы например отправить комуто файл, сам фигзнает откуда его получает :D
Это же нелепость просто.
Ведь можно както или может через какой другой компонент вместо TServerSocket&TClientSocket организовать нормальную работу.
Чтоб если пользователь1 отправил запрос на скачивание файла, то пользователь1 и получил этот файл.
Во вторых - соединения клиента лучше вообще обрабатывать в отдельном потоке - тогда просто отпадает необходимость в переборе соединений и определении клиентов - хотя значительно усложняется код.
В третьих - вопрос "где найти литературу" должен возникнуть задолго до того, как сообщение появилось на форуме. Если же не так - то тогда надо заканчивать писать фигню на форум - а найти литературу, прочесть, а затем задавать вопросы.
Литература находится в ближайшем книжном магазине либо в сети.
Хотя можете еще так попробовать:
Вот вы хотите определенному клиенту что-то отправить. Да? Тогда:
1. "Гавкните" всем подключенным клиентам чтоб они вам прислали свой идентификатор (допустим ip адрес).
{
AnsiString gav = "Ты кто?";
for(int i=0; i<ServerSocket1->Socket->ActiveConnections; i++){
ServerSocket1->Socket->Connections->SendText("gav");
}
}
2. На стороне клиента:
TCustomWinSocket *Socket)
{
AnsiString str = Socket->ReceiveText();
if (str == "Ты кто?"){
//О, нет!?!?..Они хотят знать мое имя!
ClientSocket1->Socket->SendText("192.168.1.34");
}
}
3. на стороне сервера проверяем:
TCustomWinSocket *Socket)
{
AnsiString s;
s = Socket->ReceiveText();
//ищем нашего клиента
if (s == "192.168.1.34"){
//вау! вот он. Шлем ему наше писмеЦо
Socket->SendText("Мы знаем что ТЫ делал прошлым летом!");
}
}
код так придумал - не проверял.
ну и естественно нужно пользоваться разделителями, как было предложено уважаемым kot_
это всего лишь предложение. Ну хотя и сознаюсь - не в курсе как подругому. Я пользую Indy.
А может вкратце объясните...? то что вы написали выше по сути тоже самое.
Книжку хоть одну откройте! Статьи почитайте. Инди это инди, но если Вы не знаете основные принципы работы этих инди, то будете выдовать индусский код. kot_ прав абсолютно, надо книжки читать прежде чем вопросы задавать.
А может вкратце объясните...? то что вы написали выше по сути тоже самое.
Если вкратце - то вся необходимая информация у вас есть. Вам не нужно отправлять IP адрес серверу и т.п. - в момент установки соединения все это уже есть. Т.е.:
практически тоже самое что и знаменитый индусский код
if(Bool.Length() ==5){
//
}
И говорит о том что вы очень далеки от понимания основ сетевого программирования.
TCustomWinSocket *Socket)
{
AnsiString IPClient;
for (int i=0;i<SSocket->Socket->ActiveConnections;i++)
{
IPClient=SSocket->Socket->Connections->RemoteAddress; // Получение IP клиента
if (Memo2->Lines->Strings==IPClient)
{
ShowMessage("IP: " + IPClient + " уже зарегестрирован");
break;
}
else
Memo2->Lines->Strings=IPClient; // Заносим IP клиента в Мемо
Memo1->Lines->Add("Клиент присоединился");
}
}
т.е. как уже говорилось выше "Зачем изобретать велосипед?", придумывать идентификаторы, когда можно использовать IP адрес, находящийся в сокете. Чтобы лучше разобраться с работой сокетов можно написать чат пользуясь WSASocket