Client-Server
От: MarkANix  
Дата: 15.09.06 07:10
Оценка:
Есть сервер и несколько клиентов. (Delphi6).

На сервере периодически(через 10-50 минут) возникают события о которых нужно уведомлять клиентов,

Не хочется забивать трафик переодической проверкой клиентами сервера.
Как уведомлять клиентов при возникновении события на сервере?


Был бы рад любой полезной информации.
Re: Client-Server
От: awod Россия  
Дата: 15.09.06 07:18
Оценка:
А почему бы не заставить сервер проталкивать новую инфу через сокет когда она появляется?
С уважением AWOD.
Re[2]: Client-Server
От: MarkANix  
Дата: 15.09.06 08:01
Оценка:
Здравствуйте, awod, Вы писали:

A>А почему бы не заставить сервер проталкивать новую инфу через сокет когда она появляется?


Честно говоря с сокетами еще не работал.
Если я правильно понял, информацию можно отсылать от Client сокета к Server сокету.
Тогда нужно на серверной и клиентской машинах ставить по паре Client-Server-sockets?

Я правильно понял?
Re[3]: Client-Server
От: awod Россия  
Дата: 15.09.06 09:30
Оценка:
MAN>Если я правильно понял, информацию можно отсылать от Client сокета к Server сокету.
MAN>Тогда нужно на серверной и клиентской машинах ставить по паре Client-Server-sockets?
Не надо. Достаточно чтобы с одной стороны был сервер сокет, с другой клиент. С сервера на клиент отправляется команда. Клиент в цикле чекает буфер на приём. Собствено всё
С уважением AWOD.
Re: Client-Server
От: Liris Россия http://lifeondvd.narod.ru/
Дата: 15.09.06 09:59
Оценка:
Здравствуйте, MarkANix, Вы сами нашли эти буквы?:

MAN>На сервере периодически(через 10-50 минут) возникают события о которых нужно уведомлять клиентов,


MAN>Не хочется забивать трафик переодической проверкой клиентами сервера.

MAN>Как уведомлять клиентов при возникновении события на сервере?
MAN>Был бы рад любой полезной информации.

Есть один пример. Я так делал, в похожей ситуации, и тоже на D6
Автоматизировал работу приемной комиссии ВУЗа.
1. Ложи на главную форму компонент NMUDP (в примере UdpAbitMessage)
2. Настраиваешь порты и широковещательный IP (Н-р: 192.168.0.255)
3. Событие OnDataRecieved (Это только пример )
procedure Tdm.UdpAbitMessageDataReceived(Sender: TComponent;
    NumberBytes: Integer; FromIP: string; Port: Integer);
var
    oeMsgType, PrivateMsg, WhoAddress: string;
    MyStream: TMemoryStream;
    msg, TmpStr, sStatus, sUser, sMash, sForList, sSecretar: string;
begin
    MyStream := TMemoryStream.Create;
    try
        UdpAbitMessage.ReadStream(MyStream);
        SetLength(TmpStr, NumberBytes);
        MyStream.Read(TmpStr[1], NumberBytes);
    finally
        MyStream.Free;
    end;

    if TmpStr <> '' then
    begin
        oeMsgType := '';
        msg := TmpStr;
        oeMsgType := Copy(msg, 1, Pos('*', msg) - 1);
        Delete(msg, 1, Pos('*', msg));

        if oeMsgType = 'AbitUpdate' then
        begin
            if msg <> '' then
            begin
                if Assigned(Form1) then
                begin
                    if not Form1.SpeedItem6.Enabled then Form1.SpeedItem6.Enabled := true;
                    Form1.StatusBar1.Panels[4].Text := msg;
                end;
            end;
        end;

    //SendMail
        if oeMsgType = 'AbitADMMail' then
        begin
            if Assigned(Form1) then
            begin
                OkTimeOut.Enabled := True;
                if MessageDlg(msg, mtConfirmation, [mbOk], 0) = mrOk then OkTimeOut.Enabled := False;
            end;
        end;

    //PrivateMail
        if oeMsgType = 'AbitMessaging' then
        begin
            PrivateMsg := '';
            WhoAddress := '';
            if Assigned(Form1) then
            begin
                PrivateMsg := msg;
                if Trim(PrivateMsg) = '' then Exit;
                WhoAddress := Copy(PrivateMsg, Pos(':', PrivateMsg) + 1, Pos(';', PrivateMsg) - Pos(':', PrivateMsg) - 1);
                Delete(PrivateMsg, 1, Pos(';', PrivateMsg));
                if secretar = WhoAddress then MessageDlg(PrivateMsg, mtInformation, [mbOk], 0);
            end;
        end;
        if oeMsgType = 'WHO' then
            _SendBroadcastMsg(bmIHere, 'OnLine');

        if oeMsgType = 'IHERE' then
            if Assigned(fActiveUser) then
            begin
                sUser := Copy(msg, 1, Pos('@', msg) - 1);
                Delete(msg, 1, Pos('@', msg));
                sMash := Copy(msg, 1, Pos('@', msg) - 1);
                Delete(msg, 1, Pos('@', msg));
                sStatus := Copy(msg, 1, Pos('@', msg) - 1);
                Delete(msg, 1, Pos('@', msg));
                sSecretar := Copy(msg, 1, Pos('@', msg) - 1);
                Delete(msg, 1, Pos('@', msg));
                sForList := Format('Польз.: < %s > (%s) на PC < %s > IP < %s >  (%s)', [sUser, sSecretar, sMash, FromIP, sStatus]);
                if fActiveUser.lbUsers.Items.IndexOf(sForList) = -1 then
                    fActiveUser.lbUsers.Items.Add(sForList);
            end;

    end;

end;

С помощью этого я реализовал прием и разбор сообщений. Причем сообщения разного типа. Можно и шифрование подключить
4. Процедура для отправки ответных сообщений.
procedure Tdm._SendBroadcastMsg(bmMesgType: Byte; sMessage: string);
var
    Potok: TMemoryStream;
    sForSend, sStat: string;
begin
    Potok := TMemoryStream.Create;
    case bmMesgType of
        bmWHO: begin //Кто здесь?
                sForSend := 'WHO*' + sMessage;
                try
                    Potok.Write(sForSend[1], length(sForSend));
                    UdpAbitMessage.SendStream(Potok);
                finally
                    Potok.Free;
                end;
            end;

        bmIHere: begin //Ответ !Я здесь!
                if Application.Active then
                    sStat := 'активен'
                else
                    sStat := 'неактивен';
                sForSend := 'IHERE*' + _GetCurrUser + '@' + _GetMashineName + '@' +sStat + '@' + secretar + '@' + sMessage;
                try
                    Potok.Write(sForSend[1], length(sForSend));
                    UdpAbitMessage.SendStream(Potok);
                finally
                    Potok.Free;
                end;
            end;
    end;
end;


На сервере ставь процедуру (4), а на клиентах (3) У меня (по коду поймешь) разные действия навешаны на прием разного типа сообщений.
Удачи!
... << LifeOnDVD — память в цифре >> http://LifeOnDVD.narod.ru/
Re[2]: Client-Server
От: MarkANix  
Дата: 15.09.06 10:51
Оценка:
Здравствуйте, Liris,

Большое спасибо за приведенный пример, но если я не ошибаюсь, сервер отсылает соообщение в ОТВЕТ не запрос клиента.
Т.е. клиентам нужно переодически сниффить сервер. А я бы хотел чтобы сервак уведомлял клиентов по мере надобности.

Или я ошибаюсь?
Re[4]: Client-Server
От: MarkANix  
Дата: 15.09.06 11:42
Оценка:
Здравствуйте, awod, Вы писали:

MAN>>Если я правильно понял, информацию можно отсылать от Client сокета к Server сокету.

MAN>>Тогда нужно на серверной и клиентской машинах ставить по паре Client-Server-sockets?
A>Не надо. Достаточно чтобы с одной стороны был сервер сокет, с другой клиент. С сервера на клиент отправляется команда. Клиент в цикле чекает буфер на приём. Собствено всё

Что-то не могу понять где собака порылась?

Есть две формы: Form1 и Form2.
На одной ClientSocket на другой ServerSocket(Active=true),

Это клиент:
===================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
ClientSocket1.Open;
end;

procedure TForm1.ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
begin
Socket.SendText('Hello!');
end;

procedure TForm1.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
begin
ShowMessage(Socket.ReceiveText);
end;

Это сервер:
===================================================================
procedure TForm2.Button1Click(Sender: TObject);
begin
ServerSocket1.Socket.SendText('Response');
end;

procedure TForm2.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
begin
ShowMessage(Socket.ReceiveText);
end;


При нажатии на кнопку Button1 на клиенте устанавливается соединение с серверным сокетом и опправляется текст "Hello!".
Сервер принимает текст и выдает его на экран.

Если я отсылаю сообщение обратно на клиент:
ServerSocket1.Socket.SendText('Response');

То выдается ошибка:
Windows socket error: A request to send or receive data disallowed because the socket is not connected and
(when sending on a datagram socket using a sendto call) no address was supplied (10057), on API "send"

Разве соединение не было установлено после ClientSocket1.Open?
Re[5]: Client-Server
От: MarkANix  
Дата: 15.09.06 11:48
Оценка:
Вопрос снимается

Вместо
ServerSocket1.Socket.SendText('test');

использовал:

ServerSocket1.Socket.Connections[0].SendText('test');


Сокеты приятно удивили возможность отправки сообщений обратно клиенту
Re[2]: Client-Server
От: MarkANix  
Дата: 15.09.06 12:05
Оценка:
Здравствуйте, Liris, Вы писали:

L>Есть один пример. Я так делал, в похожей ситуации, и тоже на D6

L>Автоматизировал работу приемной комиссии ВУЗа.
L>1. Ложи на главную форму компонент NMUDP (в примере UdpAbitMessage)
L>2. Настраиваешь порты и широковещательный IP (Н-р: 192.168.0.255)
L>...

А почему собственно был использован UDP протокол вместо TCP?
Re[3]: Client-Server
От: Danchik Украина  
Дата: 15.09.06 13:56
Оценка:
Здравствуйте, MarkANix, Вы писали:

MAN>Здравствуйте, Liris, Вы писали:


L>>Есть один пример. Я так делал, в похожей ситуации, и тоже на D6

L>>Автоматизировал работу приемной комиссии ВУЗа.
L>>1. Ложи на главную форму компонент NMUDP (в примере UdpAbitMessage)
L>>2. Настраиваешь порты и широковещательный IP (Н-р: 192.168.0.255)
L>>...

MAN>А почему собственно был использован UDP протокол вместо TCP?


Так проще броадкастить сообщения. Не надо знать какие клиенты есть. Просто плюхнули сообщение в сеть (не указывая точного IP клиента). Клиент поймал датаграму и насладился

Я так и не понял, в чем у вас проблема? Вы на чем написали сервер? На синхронных сокетах Indy?
Re[3]: Client-Server
От: Liris Россия http://lifeondvd.narod.ru/
Дата: 15.09.06 15:21
Оценка:
Здравствуйте, MarkANix, Вы писали:

MAN>Большое спасибо за приведенный пример, но если я не ошибаюсь, сервер отсылает соообщение в ОТВЕТ не запрос клиента.

MAN>Т.е. клиентам нужно переодически сниффить сервер. А я бы хотел чтобы сервак уведомлял клиентов по мере надобности.

MAN>Или я ошибаюсь?

Ошибаетесь. У сервера на нужные события вешаете процедуру _SendBroadcastMsg и он в сеть кидает инфу. Даже думать не нужно, кто в сети, сколько подключеных, активных... А клиентам возмите процедуру из пункта (3). Если они в сети, обязательно получать широковещательный пакет. Зачем такому пакету TCP, т.е. контроль доставки? Транспорт UDP нормально работает, если сеть работает
А для защиты от посторонних глаз (снифферов) используйте шифрование потоков или строк.
Удачи!
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Client-Server
От: Liris Россия http://lifeondvd.narod.ru/
Дата: 15.09.06 15:54
Оценка:
Здравствуйте, MarkANix, Вы писали:

MAN>А почему собственно был использован UDP протокол вместо TCP?

см. Re[3]: Client-Server
Автор: Liris
Дата: 15.09.06
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: Client-Server
От: MarkANix  
Дата: 15.09.06 16:17
Оценка:
D>Я так и не понял, в чем у вас проблема? Вы на чем написали сервер? На синхронных сокетах Indy?

Я как раз выбираю компоненты и протоколы. Проект: БД на сервере + сервер приложений + клиенты. Собственно вопрос касается сервера приложений.

Раньше думал использовать Indy + HTTP. Потом подумал: если планов выносить проект за интранет нет, то удобнее будет использовать TCP/Sockets.

При детальном изучении рынка нашел высокуровневые решения: RealThinClient, MsgConnect, RemObjects. Сейчас вот изучаю, стоит ли всю логику писать самому или использовать указанные компоненты.

Если кто их юзал поделитесь впечатлениями
Re[4]: Client-Server
От: MarkANix  
Дата: 15.09.06 16:22
Оценка:
Здравствуйте, Liris, Вы писали:

MAN>>Или я ошибаюсь?

L>Ошибаетесь. У сервера на нужные события вешаете процедуру _SendBroadcastMsg и он в сеть кидает инфу. Даже думать не нужно, кто в сети, сколько подключеных, активных... А клиентам возмите процедуру из пункта (3). Если они в сети, обязательно получать широковещательный пакет. Зачем такому пакету TCP, т.е. контроль доставки? Транспорт UDP нормально работает, если сеть работает
L>А для защиты от посторонних глаз (снифферов) используйте шифрование потоков или строк.
L>Удачи!

Теперь понятно. Правда нужно будет отслеживать еще за доставкой UDP пакетов. Клиенты должны 99.9% получить уведомление о событиях на сервере.
Re[5]: Client-Server
От: Danchik Украина  
Дата: 15.09.06 16:56
Оценка:
Здравствуйте, MarkANix, Вы писали:

D>>Я так и не понял, в чем у вас проблема? Вы на чем написали сервер? На синхронных сокетах Indy?


MAN>Я как раз выбираю компоненты и протоколы. Проект: БД на сервере + сервер приложений + клиенты. Собственно вопрос касается сервера приложений.


MAN>Раньше думал использовать Indy + HTTP. Потом подумал: если планов выносить проект за интранет нет, то удобнее будет использовать TCP/Sockets.


MAN>При детальном изучении рынка нашел высокуровневые решения: RealThinClient, MsgConnect, RemObjects. Сейчас вот изучаю, стоит ли всю логику писать самому или использовать указанные компоненты.


MAN>Если кто их юзал поделитесь впечатлениями


Попробуйте MTDORB
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.