🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.cppbuilder.internet.socket
24 messages
24 total messages Started by Gary D Sat, 22 Oct 2005 01:18
sockets????
#3346
Author: Gary D
Date: Sat, 22 Oct 2005 01:18
18 lines
1689 bytes
I need to have a one way broadcast from a "server" to multiple clients, here 
is the scenario:

A server watches for events that happen in special situations, this part of 
my program is
already runnig, BUT I need to add code that can broadcast (unsolicited) that 
the event(s)
occurred. At that point any client that happened to be listening could 
update itself without
having to watch all the same things the server is already watching.

Is a socket the best way to do this? I have looked into COM and found that 
COM servers
will not broadcast an unsolicited message. I can probably work around this 
but wish I didn't
have to because the server will have to do extra work holding open a 
triggered event
until something happens to complete the sequence. 
Re: sockets????
#3348
Author: Remy Lebeau (TeamB)
Date: Sat, 22 Oct 2005 02:11
25 lines
1797 bytes
"Gary D" <gcdesroches@nctc.com> wrote in message
news:43599303@newsgroups.borland.com...

> Is a socket the best way to do this?

A socket is one way to do it.

> I have looked into COM and found that COM servers
> will not broadcast an unsolicited message.

Yes, they will.  I have COM servers that broadcast events just fine.

> the server will have to do extra work holding open a triggered
> event until something happens to complete the sequence.

Use multiple threads.  Have one thread monitoring the events, then have
another thread that broadcasts events to clients.  When a monitored event
occurs, copy the relative information to a queue in the broadcast thread and
then go back to monitoring for new events.  This way, the broadast thread is
run in parallel to the monitoring thread and the monitoring is not waiting
for the broadcast to finish, and vice versa.


Gambit
Re: sockets????
#3349
Author: Gary D
Date: Sun, 23 Oct 2005 16:37
46 lines
2740 bytes
If you can make a COM server broadcast without needing a request from a
client
can you tell me how you did it? Borland support says it can't be done.
( Remember it's an UNSOLICITED broadcast I'm after, no client involvment
other than receiving )

I have multi-threads running already so that part you could skip.
I have a server client demo running also, so the only thing I need to see is
how you get
around the server's need for the request from the client.

BTW, I don't even need to send any "data" I just need the server to fire an
event in the client.
That event will already contain everything the client needs.

"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message 
news:43599f5f$1@newsgroups.borland.com...
>
> "Gary D" <gcdesroches@nctc.com> wrote in message
> news:43599303@newsgroups.borland.com...
>
>> Is a socket the best way to do this?
>
> A socket is one way to do it.
>
>> I have looked into COM and found that COM servers
>> will not broadcast an unsolicited message.
>
> Yes, they will.  I have COM servers that broadcast events just fine.
>
>> the server will have to do extra work holding open a triggered
>> event until something happens to complete the sequence.
>
> Use multiple threads.  Have one thread monitoring the events, then have
> another thread that broadcasts events to clients.  When a monitored event
> occurs, copy the relative information to a queue in the broadcast thread 
> and
> then go back to monitoring for new events.  This way, the broadast thread 
> is
> run in parallel to the monitoring thread and the monitoring is not waiting
> for the broadcast to finish, and vice versa.
>
>
> Gambit
>
> 
Re: sockets????
#3350
Author: Remy Lebeau (TeamB)
Date: Sun, 23 Oct 2005 17:10
48 lines
3176 bytes
"Gary D" <gcdesroches@nctc.com> wrote in message 
news:435bbbf2$1@newsgroups.borland.com...

> If you can make a COM server broadcast without needing a request
> from a client can you tell me how you did it?

Event sinks.  A client registers a sink with the server, and then the server 
can trigger events to that sink whenever it wants.  A common way to do that 
is via Connection Points.  When you create a new COM object in the IDE's 
ActiveX wizards, you have an option to "Generate Event Support".  This 
option adds an additional IDispatch-derived interface to your Type Library 
where you can then define your event methods.  The COM object's Impl class 
will then have a TEvent_... class added to its ancestor list which 
implements Fire_...() methods for the events.  The server code can call 
these methods at any time to trigger events in connected clients.  The 
client's code can then derive a class from that interface, or alternatively 
use the VCL's TEventDispatcher class, to implement the event handling as 
needed.  In the case of TEventDispatcher, it has a ConnnectServer() method 
that you can use to hook up the TEventDispatcher to your COM object 
instance.  If you don't use TEventDispatcher, then you have to manually 
query the COM object for the IConnectionPointContainer interface, call its 
FindConnectionPoint() method to get an IConnectionPoint interface, and then 
finally call its Advise() method passing it an instance of your sink class.

Refer to the following articles for more details:

    Events/Callbacks
    http://www.techvanguards.com/com/concepts/events.asp

    Implementing an Event Framework
    http://www.techvanguards.com/com/tutorials/eventsystem.asp

The code examples are in Delphi, but the concepts can be applied to C++ as 
well.

> Borland support says it can't be done.

What EXACTLY was said?

> ( Remember it's an UNSOLICITED broadcast I'm after, no client
> involvment other than receiving )

The client has to register its interest in receiving events.  You can do 
that right after instantiating the COM object.


Gambit 
Re: sockets????
#3352
Author: Gary D
Date: Mon, 24 Oct 2005 10:38
60 lines
3616 bytes
Thank you for the help, I am totally new at COM so I have had a rough ride 
even getting this far.
I at least understand what I'm reading here now. I will try to work through 
your explanation
and see if I can get it to work.

Gary D

"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message 
news:435bc353$1@newsgroups.borland.com...
>
> "Gary D" <gcdesroches@nctc.com> wrote in message 
> news:435bbbf2$1@newsgroups.borland.com...
>
>> If you can make a COM server broadcast without needing a request
>> from a client can you tell me how you did it?
>
> Event sinks.  A client registers a sink with the server, and then the 
> server can trigger events to that sink whenever it wants.  A common way to 
> do that is via Connection Points.  When you create a new COM object in the 
> IDE's ActiveX wizards, you have an option to "Generate Event Support". 
> This option adds an additional IDispatch-derived interface to your Type 
> Library where you can then define your event methods.  The COM object's 
> Impl class will then have a TEvent_... class added to its ancestor list 
> which implements Fire_...() methods for the events.  The server code can 
> call these methods at any time to trigger events in connected clients. 
> The client's code can then derive a class from that interface, or 
> alternatively use the VCL's TEventDispatcher class, to implement the event 
> handling as needed.  In the case of TEventDispatcher, it has a 
> ConnnectServer() method that you can use to hook up the TEventDispatcher 
> to your COM object instance.  If you don't use TEventDispatcher, then you 
> have to manually query the COM object for the IConnectionPointContainer 
> interface, call its FindConnectionPoint() method to get an 
> IConnectionPoint interface, and then finally call its Advise() method 
> passing it an instance of your sink class.
>
> Refer to the following articles for more details:
>
>    Events/Callbacks
>    http://www.techvanguards.com/com/concepts/events.asp
>
>    Implementing an Event Framework
>    http://www.techvanguards.com/com/tutorials/eventsystem.asp
>
> The code examples are in Delphi, but the concepts can be applied to C++ as 
> well.
>
>> Borland support says it can't be done.
>
> What EXACTLY was said?
>
>> ( Remember it's an UNSOLICITED broadcast I'm after, no client
>> involvment other than receiving )
>
> The client has to register its interest in receiving events.  You can do 
> that right after instantiating the COM object.
>
>
> Gambit
> 
Re: sockets????
#3193
Author: Gary D
Date: Tue, 25 Oct 2005 21:54
89 lines
4567 bytes
Sorry I didn't answer your question about what exactly was said. Here is the 
complete text:

My Question was:

Why can't the server just call Trigger() itself?  // NOTE: Trigger is the 
function that the server owns that responds to client requests.

somefunction()
{
    Doing the server thing...
    if( Oh, look! Something important happened!...)
        Trigger();
}

That would accomplish what I am after because the message box would become:

void __fastcall TForm1::OnEvent1(BSTR* Message)
{
    //  ShowMessage("Fired now");
    Do the refresh_info_thing();
}


???? Gary

and the answer came back:

     Servers don't really have that kind of logic.  They pretty much sit 
there and wait for requests from clients.  In other words, servers aren't 
supposed to "push out" services on their own; they're only supposed to wait 
for clients to request services and then fulfill those requests.
     Another way to see it is that servers aren't designed to sit there 
executing code on their own.  They only spring to action when a client tells 
them to.  A COM server isn't any different.


"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message 
news:435bc353$1@newsgroups.borland.com...
>
> "Gary D" <gcdesroches@nctc.com> wrote in message 
> news:435bbbf2$1@newsgroups.borland.com...
>
>> If you can make a COM server broadcast without needing a request
>> from a client can you tell me how you did it?
>
> Event sinks.  A client registers a sink with the server, and then the 
> server can trigger events to that sink whenever it wants.  A common way to 
> do that is via Connection Points.  When you create a new COM object in the 
> IDE's ActiveX wizards, you have an option to "Generate Event Support". 
> This option adds an additional IDispatch-derived interface to your Type 
> Library where you can then define your event methods.  The COM object's 
> Impl class will then have a TEvent_... class added to its ancestor list 
> which implements Fire_...() methods for the events.  The server code can 
> call these methods at any time to trigger events in connected clients. 
> The client's code can then derive a class from that interface, or 
> alternatively use the VCL's TEventDispatcher class, to implement the event 
> handling as needed.  In the case of TEventDispatcher, it has a 
> ConnnectServer() method that you can use to hook up the TEventDispatcher 
> to your COM object instance.  If you don't use TEventDispatcher, then you 
> have to manually query the COM object for the IConnectionPointContainer 
> interface, call its FindConnectionPoint() method to get an 
> IConnectionPoint interface, and then finally call its Advise() method 
> passing it an instance of your sink class.
>
> Refer to the following articles for more details:
>
>    Events/Callbacks
>    http://www.techvanguards.com/com/concepts/events.asp
>
>    Implementing an Event Framework
>    http://www.techvanguards.com/com/tutorials/eventsystem.asp
>
> The code examples are in Delphi, but the concepts can be applied to C++ as 
> well.
>
>> Borland support says it can't be done.
>
> What EXACTLY was said?
>
>> ( Remember it's an UNSOLICITED broadcast I'm after, no client
>> involvment other than receiving )
>
> The client has to register its interest in receiving events.  You can do 
> that right after instantiating the COM object.
>
>
> Gambit
> 
Re: sockets????
#3194
Author: Remy Lebeau (TeamB)
Date: Tue, 25 Oct 2005 22:37
24 lines
2056 bytes
"Gary D" <gcdesroches@nctc.com> wrote in message
news:435ea916$1@newsgroups.borland.com...

> Why can't the server just call Trigger() itself?  // NOTE: Trigger
> is the function that the server owns that responds to client requests.

The server *CAN* call Trigger() whenever it needs to.  Trigger() can then
call the Fire_...() method for whichever event(s) its wants to, and those
events will be called in the client's event sink.

> and the answer came back:

Borland's answer is completely wrong.  Servers *DO* have that kind of logic
available.  Connection Points are designed exactly to handle the kind of
Push model that Borland says servers can't have.  I know it works because I
have several COM servers that push unsolicited events to clients in response
to external triggers (hardware events, file changes, etc).  Also, it is
possible to design a COM server inside an NT service, such that the COM
server *IS* executing code on its own without having any clients connected
at all.


Gambit
Re: sockets????
#3221
Author: Gary D
Date: Sat, 29 Oct 2005 12:15
67 lines
3835 bytes
This is the code that creates a server connection and fires the event ( in 
the demo I was given nothing is done but to display a messagebox )

void __fastcall TClientWin::Button1Click(TObject *Sender)
{
     FTestEventsImpl = CoTestEventsImpl::Create();

     FEventSink.OnEvent1 = OnEvent1;
     FEventSink.Connect(FTestEventsImpl);

     FTestEventsImpl.Trigger();
}
//---------------------------------------------------------------------------
void __fastcall TClientWin::OnEvent1(BSTR* Message)
{
    ShowMessage("Client Event Fired");
}
//---------------------------------------------------------------------------

The server is a blank window. It just appears(when the FTestEventsImpl = 
CoTestEventsImpl::Create(); code executes? )
everything else is done in the COM library / Library table. ( right??)

I do not understand COM at all outside of intellectually knowing what it 
does.
Borland is no help, I paid them like $2000.00 for tech support to have them 
tell me I can't do what you say I can do.
PLEASE, can you tell me what to do to get the server to fire the OnEvent1 of 
the client when the SERVER wants to
and not because the client asked? I understand that the client must connect 
first to announce it self, but I don't understand
how to access the connection at the server's end once it is inplace. I have 
tried for days and only became more frustrated.



"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message 
news:435eb30b@newsgroups.borland.com...
>
> "Gary D" <gcdesroches@nctc.com> wrote in message
> news:435ea916$1@newsgroups.borland.com...
>
>> Why can't the server just call Trigger() itself?  // NOTE: Trigger
>> is the function that the server owns that responds to client requests.
>
> The server *CAN* call Trigger() whenever it needs to.  Trigger() can then
> call the Fire_...() method for whichever event(s) its wants to, and those
> events will be called in the client's event sink.
>
>> and the answer came back:
>
> Borland's answer is completely wrong.  Servers *DO* have that kind of 
> logic
> available.  Connection Points are designed exactly to handle the kind of
> Push model that Borland says servers can't have.  I know it works because 
> I
> have several COM servers that push unsolicited events to clients in 
> response
> to external triggers (hardware events, file changes, etc).  Also, it is
> possible to design a COM server inside an NT service, such that the COM
> server *IS* executing code on its own without having any clients connected
> at all.
>
>
> Gambit
>
> 
Re: sockets????
#3222
Author: Gary D
Date: Sat, 29 Oct 2005 12:30
58 lines
3193 bytes
Let me ask a more specific question...

This is the Trigger() code in the server:

STDMETHODIMP TTestEventsImplImpl::Trigger()
{
    WideString strName;

    bool Fire_The_Event = true;
    if ( Fire_The_Event == true )
        Fire_Event1(&strName);

     return S_OK;
}

The bool Fire_The_Event = 1; if( Fire_The_Event == ??? ) is supposed to show 
that if Fire_The_Event is true the event fires and if not it won't.
I get that.

So here is the thing I am stuck on. How do I replace a local bool with an 
external one which will use the client's existing connection?
( and accept new connections ) I can't figure out how to access Trigger() 
inside the Server Code at all, let alone get an instance of it
that has active connection(s) to the client(s).



"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message 
news:435eb30b@newsgroups.borland.com...
>
> "Gary D" <gcdesroches@nctc.com> wrote in message
> news:435ea916$1@newsgroups.borland.com...
>
>> Why can't the server just call Trigger() itself?  // NOTE: Trigger
>> is the function that the server owns that responds to client requests.
>
> The server *CAN* call Trigger() whenever it needs to.  Trigger() can then
> call the Fire_...() method for whichever event(s) its wants to, and those
> events will be called in the client's event sink.
>
>> and the answer came back:
>
> Borland's answer is completely wrong.  Servers *DO* have that kind of 
> logic
> available.  Connection Points are designed exactly to handle the kind of
> Push model that Borland says servers can't have.  I know it works because 
> I
> have several COM servers that push unsolicited events to clients in 
> response
> to external triggers (hardware events, file changes, etc).  Also, it is
> possible to design a COM server inside an NT service, such that the COM
> server *IS* executing code on its own without having any clients connected
> at all.
>
>
> Gambit
>
> 
Re: sockets????
#3223
Author: Remy Lebeau (TeamB)
Date: Sat, 29 Oct 2005 18:24
17 lines
1795 bytes
"Gary D" <gcdesroches@nctc.com> wrote in message
news:436367ef$1@newsgroups.borland.com...

> This is the code that creates a server connection and fires the event

And?  Does it actually work for you?

> PLEASE, can you tell me what to do to get the server to
> fire the OnEvent1 of the client when the SERVER wants
> to and not because the client asked?

I already told you earlier what to do on the server side - call the
Fire_...() method for the event wheverever you want to.


Gambit
Re: sockets????
#3224
Author: Remy Lebeau (TeamB)
Date: Sat, 29 Oct 2005 18:28
36 lines
2254 bytes
"Gary D" <gcdesroches@nctc.com> wrote in message
news:43636b7d@newsgroups.borland.com...

>         Fire_Event1(&strName);

You should not be using the & operator there:

    Fire_Event1(strName);

> So here is the thing I am stuck on. How do I replace a local bool
> with an external one which will use the client's existing connection?

You don't.

> ( and accept new connections )

That is handled automatically by COM for you.  Every time
TTestEventsImplImpl is instantiated, that instance represents a new client
connection.

> I can't figure out how to access Trigger() inside the Server Code at all

Trigger() should be a public method of the TTestEventsImplImpl class.  Given
a pointer to a TTestEventsImplImpl instance, you can call Trigger() on it.

> let alone get an instance of it that has active connection(s) to the
client(s).

Simply keep a list of instantiated TTestEventsImplImpl instances.  In
TTestEventsImplImpl's constructor, add the 'this' pointer to the list.  In
the destructor, remove the 'this' pointer from the list.  Then the server
can loop through the list when needed.


Gambit
Re: sockets????
#3225
Author: Gary D
Date: Sat, 29 Oct 2005 21:42
25 lines
2048 bytes
Yes the demo works perfectly but I didn't write it, Borland support did.
I do not understand how it works only that it does.


"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message 
news:4363be5e$1@newsgroups.borland.com...
>
> "Gary D" <gcdesroches@nctc.com> wrote in message
> news:436367ef$1@newsgroups.borland.com...
>
>> This is the code that creates a server connection and fires the event
>
> And?  Does it actually work for you?
>
>> PLEASE, can you tell me what to do to get the server to
>> fire the OnEvent1 of the client when the SERVER wants
>> to and not because the client asked?
>
> I already told you earlier what to do on the server side - call the
> Fire_...() method for the event wheverever you want to.
>
>
> Gambit
>
> 
Re: sockets????
#3226
Author: Gary D
Date: Sat, 29 Oct 2005 22:01
104 lines
4473 bytes
"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message 
news:4363bf65$1@newsgroups.borland.com...
>
>>         Fire_Event1(&strName);
>
> You should not be using the & operator there:
>
>    Fire_Event1(strName);

OK, its not important as it isn't part of my project anyway, only part of 
Borland's Demo.


>
>> So here is the thing I am stuck on. How do I replace a local bool
>> with an external one which will use the client's existing connection?
>
> You don't.
>

OK... I think I see where your going with this but...

>> ( and accept new connections )
>
> That is handled automatically by COM for you.  Every time
> TTestEventsImplImpl is instantiated, that instance represents a new client
> connection.
>
>> I can't figure out how to access Trigger() inside the Server Code at all
>
> Trigger() should be a public method of the TTestEventsImplImpl class. 
> Given
> a pointer to a TTestEventsImplImpl instance, you can call Trigger() on it.
>

Yup I'll just bet I could too if ONLY:

>> let alone get an instance of it that has active connection(s) to the
> client(s).
>
> Simply keep a list of instantiated TTestEventsImplImpl instances.  In
> TTestEventsImplImpl's constructor, add the 'this' pointer to the list.  In
> the destructor, remove the 'this' pointer from the list.  Then the server
> can loop through the list when needed.
>

I can get get tech support to explain how to get a list of instances if I 
can get the rest figured out.

> TTestEventsImplImpl's constructor, add the 'this' pointer to the list

The help files say "this" is implied. What "type" is "this" I don't know.
I had less trouble learning to TALK than I'm having learning this.
Is this the list your talking about?? What should it look like when added?
Also there is no destructor. If I add one and ever refresh the type library
for some reason like adding new functions won't it vanish?
I'm not stupid but I feel that way right now.

class ATL_NO_VTABLE TTestEventsImplImpl :
  public CComObjectRootEx<CComSingleThreadModel>,
  public CComCoClass<TTestEventsImplImpl, &CLSID_TestEventsImpl>,
  public IConnectionPointContainerImpl<TTestEventsImplImpl>,
  public TEvents_TestEventsImpl<TTestEventsImplImpl>,
  public IDispatchImpl<ITestEventsImpl, &IID_ITestEventsImpl, 
&LIBID_TestEventsTypeLib>
{
public:
  TTestEventsImplImpl()
  {
  }
  // Data used when registering Object
  //
  DECLARE_THREADING_MODEL(otApartment);
  DECLARE_PROGID("TestEventsTypeLib.TestEventsImpl");
  DECLARE_DESCRIPTION("");

  // Function invoked to (un)register object
  //
  static HRESULT WINAPI UpdateRegistry(BOOL bRegister)
  {
    TTypedComServerRegistrarT<TTestEventsImplImpl>
    regObj(GetObjectCLSID(), GetProgID(), GetDescription());
    return regObj.UpdateRegistry(bRegister);
  }


BEGIN_COM_MAP(TTestEventsImplImpl)
  COM_INTERFACE_ENTRY(ITestEventsImpl)
  COM_INTERFACE_ENTRY2(IDispatch, ITestEventsImpl)
  COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)
END_COM_MAP()

BEGIN_CONNECTION_POINT_MAP(TTestEventsImplImpl)
  CONNECTION_POINT_ENTRY(DIID_ITestEventsImplEvents)
END_CONNECTION_POINT_MAP()

// ITestEventsImpl
public:

  STDMETHOD(Trigger());
};

#endif //TestEventsImplImplH
Re: sockets????
#3227
Author: Remy Lebeau (TeamB)
Date: Mon, 31 Oct 2005 07:33
48 lines
3146 bytes
"Gary D" <gcdesroches@nctc.com> wrote in message 
news:4363f179$1@newsgroups.borland.com...

> The help files say "this" is implied.

Yes, but it can also be referenced explicitally as well.  That is why the 
actual 'this' keyword exists at all.

> What "type" is "this" I don't know.

It is a compiler-provided pointer that is always the type of the class whose 
method is accessing the 'this' pointer.  In other words, if 'this' is being 
used inside of TSomeClass::DoSomething(), then 'this' is of type TSomeClass.

> Is this the list your talking about??

No.  I am referring about a user-defined list, such as a TList or 
TThreadList object, that is managed in code and holds pointers to active 
Impl classs instances.

> What should it look like when added?

For example:

http://groups.google.com/group/borland.public.cppbuilder.activex/msg/5cd00c5861a2be90?hl=en&

You can read the following discussion for more details about why I use the 
above-linked code:

http://groups.google.com/groups?as_q=tthreadlist&num=10&scoring=r&hl=en&as_epq=&as_oq=&as_eq=&as_ugroup=*activex*&as_usubject=&as_uauthors=remy+lebeau&lr=&as_drrb=q&as_qdr=&as_mind=1&as_minm=1&as_miny=1981&as_maxd=30&as_maxm=10&as_maxy=2005&safe=off

> Also there is no destructor.

Yes, there is.  Every class has a destructor, just like every class has a 
constructor.  If one is not provided in code, the compiler provides a 
default one implicitally.  The code can declare an explicit one to override 
the default one.

> If I add one and ever refresh the type library for some reason
> like adding new functions won't it vanish?

No.  Refreshing the type library does not recreate the entire Impl files, 
only the TLB files.  The refresh will append/remove the particular changes 
from the Impl files, but will otherwise leave any user-defined code alone.


Gambit 
Re: sockets????
#3259
Author: Gary D
Date: Tue, 01 Nov 2005 02:33
43 lines
2744 bytes
I added the code for the TTheadList and got it to compile without a problem.
I still can not call Trigger(); from the server side.
It IS public as you said but it is part of the COM class which I am 
assuminig
means I need to have an instance of the class on the server side to be able 
to
access Trigger() from.  MyClass->Trigger(); ??

I can get instances of the Implementation but get access violations if I try 
to
use it or the server will just lock up. calling Trigger() outside the class
will simply not compile. I get not a member errors etc. I looked at the
client side and see that there is this:

     FEventSink.OnEvent1 = OnEvent1;
     FEventSink.Connect(FTestEventsImpl);

but I don't know how it works, if I need it on the server side
or how to set it up if I do need it.

My forehead is bleeding from beating it against the wall.

"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message 
news:4363be5e$1@newsgroups.borland.com...
>
> "Gary D" <gcdesroches@nctc.com> wrote in message
> news:436367ef$1@newsgroups.borland.com...
>
>> This is the code that creates a server connection and fires the event
>
> And?  Does it actually work for you?
>
>> PLEASE, can you tell me what to do to get the server to
>> fire the OnEvent1 of the client when the SERVER wants
>> to and not because the client asked?
>
> I already told you earlier what to do on the server side - call the
> Fire_...() method for the event wheverever you want to.
>
>
> Gambit
>
> 
Re: sockets????
#3264
Author: Remy Lebeau (TeamB)
Date: Tue, 01 Nov 2005 06:46
52 lines
3584 bytes
"Gary D" <gcdesroches@nctc.com> wrote in message 
news:4366d403@newsgroups.borland.com...

> I added the code for the TTheadList and got it to compile
> without a problem. I still can not call Trigger(); from the server side.

Then you are still not using it properly.  Please show your actual code. 
This is not that hard to implement.  I've already given you the pieces for 
it.  And I know it works because I use it all the time in my own COM 
servers.

> It IS public as you said but it is part of the COM class which I am 
> assuminig means I need to have an instance of the class on the
> server side to be able to access Trigger() from.  MyClass->Trigger(); ??

Of course you do, and you do have such an instance available.  Everytime the 
COM object is instantiated by a client, an instance of your class is created 
on the server side.  That is the whole purpose of the list code I gave you - 
so that your server code has access to all active instances of the class.

> I can get instances of the Implementation but get access violations if I
> try to use it or the server will just lock up.

Then you re not using it correctly.

> calling Trigger() outside the class will simply not compile.
> I get not a member errors etc.

Then you are not accessing it correctly.

> I looked at the client side and see that there is this:
>
>     FEventSink.OnEvent1 = OnEvent1;
>     FEventSink.Connect(FTestEventsImpl);
>
> but I don't know how it works

You did not read the articles I pointed you to, did you?  The client's Sink 
is implemented in terms of the IConnectionPoint interface.  Connect() 
queries the COM object for the IConnectionPointContainer interface, and from 
that then obtains the IConnectionPoint interface for your events.  The 
client then calls IConnectionPoint::Advise(), which psses an IDuspatch 
interface to your server.  On the server side, every time you call one of 
the Fire_...() methods, the client's IDispatch::Invoke() method is called, 
specifying the ID and parameters of the fired event.  All of this is handled 
transparently for you.  The only thing you have to concern yourself with in 
your own code is connecting the Sink to the client side object, and then 
calling the desired Fire_...() methods on the server side.


Gambit 
Re: sockets????
#3126
Author: Gary D
Date: Tue, 01 Nov 2005 23:08
86 lines
4140 bytes
Here is the TestEventsImplImpl.cpp File as modified to add your code:
I will Follow this with another message or 2 showing the rest of the files 
you need to see.

// TESTEVENTSIMPLIMPL : Implementation of TTestEventsImplImpl (CoClass: 
TestEventsImpl, Interface: ITestEventsImpl)

#include <vcl.h>
#pragma hdrstop

#include "TESTEVENTSIMPLIMPL.H"
#include "frmServer.h"

/////////////////////////////////////////////////////////////////////////////
//---------------------------------------------------------------------------
TThreadList* TTestEventsImplImpl::InterfaceList = NULL;  // Code added from 
newsgroup info
//---------------------------------------------------------------------------
TTestEventsImplImpl::TTestEventsImplImpl()    // Function Def added from 
newsgroup info
{
    if(!InterfaceList)
        InterfaceList = new TThreadList;
    if(InterfaceList)
        InterfaceList->Add(this);
}
//---------------------------------------------------------------------------
TTestEventsImplImpl::~TTestEventsImplImpl()   // Function Def added from 
newsgroup info
{
      if(InterfaceList)
      {
          TList *list = InterfaceList->LockList();
          int index = list->IndexOf(this);

          if(index > -1)
              list->Delete(index);

          int count = list->Count;
          InterfaceList->UnlockList();

          if(count < 1)
          {
              delete InterfaceList;
              InterfaceList = NULL;
          }
      }
}
//---------------------------------------------------------------------------
// TTestEventsImplImpl
STDMETHODIMP TTestEventsImplImpl::Trigger()                 // Existing 
Function
{
    WideString strName;                                     // Existing Code

    TTestEventsImplImpl *pIntf = NULL;                      // Code added 
from newsgroup info
    TList *list = InterfaceList->LockList();                // Code added 
from newsgroup info

    for(int x = 0; x < list->Count; x++)                    // Code added 
from newsgroup info
    {
        try                                                 // Code added 
from newsgroup info
        {
            pIntf = (TTestEventsImplImpl *)list->Items[x];  // Code added 
from newsgroup info
            if(pIntf)                                       // Code added 
from newsgroup info
                pIntf->Fire_Event1(&strName);               // Code Modified 
from newsgroup info
        }
        catch(...) { }                                      // Code added 
from newsgroup info

    }

    InterfaceList->UnlockList();                            // Code added 
from newsgroup info

//    Fire_Event1(strName);                                   // Existing 
Code
    return S_OK;                                            // Existing Code
}
//---------------------------------------------------------------------------
Re: sockets????
#3127
Author: Gary D
Date: Tue, 01 Nov 2005 23:09
75 lines
3543 bytes
This is the Header file
// TESTEVENTSIMPLIMPL.H : Declaration of the TTestEventsImplImpl

#ifndef TestEventsImplImplH
#define TestEventsImplImplH

#define ATL_APARTMENT_THREADED

#include "TestEventsTypeLib_TLB.h"


/////////////////////////////////////////////////////////////////////////////
// TTestEventsImplImpl     Implements ITestEventsImpl, default interface of 
TestEventsImpl
//                  and ITestEventsImplEvents, the default source interface
// ThreadingModel : Apartment
// Dual Interface : TRUE
// Event Support  : TRUE
// Default ProgID : Project1.TestEventsImpl
// Description    :
/////////////////////////////////////////////////////////////////////////////
class ATL_NO_VTABLE TTestEventsImplImpl :
  public CComObjectRootEx<CComSingleThreadModel>,
  public CComCoClass<TTestEventsImplImpl, &CLSID_TestEventsImpl>,
  public IConnectionPointContainerImpl<TTestEventsImplImpl>,
  public TEvents_TestEventsImpl<TTestEventsImplImpl>,
  public IDispatchImpl<ITestEventsImpl, &IID_ITestEventsImpl, 
&LIBID_TestEventsTypeLib>
{
public:
  // InterfaceList keeps a list of active client connections so the server 
can
  // fire an event(s) in each connection every time
  static TThreadList *InterfaceList;        // Code added from newsgroup 
info

  TTestEventsImplImpl();                     // Existing Code ( Funtion was 
empty )

  ~TTestEventsImplImpl();                    // Code added from newsgroup 
info

  // Data used when registering Object
  //
  DECLARE_THREADING_MODEL(otApartment);
  DECLARE_PROGID("TestEventsTypeLib.TestEventsImpl");
  DECLARE_DESCRIPTION("");

  // Function invoked to (un)register object
  //
  static HRESULT WINAPI UpdateRegistry(BOOL bRegister)
  {
    TTypedComServerRegistrarT<TTestEventsImplImpl>
    regObj(GetObjectCLSID(), GetProgID(), GetDescription());
    return regObj.UpdateRegistry(bRegister);
  }


BEGIN_COM_MAP(TTestEventsImplImpl)
  COM_INTERFACE_ENTRY(ITestEventsImpl)
  COM_INTERFACE_ENTRY2(IDispatch, ITestEventsImpl)
  COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)
END_COM_MAP()

BEGIN_CONNECTION_POINT_MAP(TTestEventsImplImpl)
  CONNECTION_POINT_ENTRY(DIID_ITestEventsImplEvents)
END_CONNECTION_POINT_MAP()

// ITestEventsImpl
public:

  STDMETHOD(Trigger());
};

#endif //TestEventsImplImplH
Re: sockets????
#3128
Author: Gary D
Date: Tue, 01 Nov 2005 23:16
30 lines
2429 bytes
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

Here is how I am trying to fire the Trigger event.
Code completion opens a window showing Trigger() as available when I
type TestEventsImplImpl->
so what stupid thing am I doing?

#include "frmServer.h"
#include "TestEventsImplImpl.h"
#include "TestEventsTypeLib_TLB.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TServerWin *ServerWin;
TTestEventsImplImpl *TestEventsImplImpl;
//---------------------------------------------------------------------------
__fastcall TServerWin::TServerWin(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TServerWin::Button1Click(TObject *Sender)
{
    TestEventsImplImpl->Trigger(); // This gets an access violation when 
executed
}
//---------------------------------------------------------------------------
Re: sockets????
#3129
Author: Bob Gonder
Date: Wed, 02 Nov 2005 03:22
9 lines
1502 bytes
Gary D wrote:

>TTestEventsImplImpl *TestEventsImplImpl;

TestEventsImplImpl  doesn't point to anything, so access violation is
right.

>    TestEventsImplImpl->Trigger(); // This gets an access violation when 
>executed
Re: sockets????
#3133
Author: Remy Lebeau (TeamB)
Date: Wed, 02 Nov 2005 08:59
12 lines
1555 bytes
"Gary D" <gcdesroches@nctc.com> wrote in message
news:4367f76b@newsgroups.borland.com...

>     TestEventsImplImpl->Trigger();
> This gets an access violation when executed

Of course it does.  You are calling Trigger() on an uninitialized pointer.
You have not instantiated the TestEventsImplImpl class at all.


Gambit
Re: sockets????
#3134
Author: Remy Lebeau (TeamB)
Date: Wed, 02 Nov 2005 09:04
140 lines
5249 bytes
"Gary D" <gcdesroches@nctc.com> wrote in message
news:4367f582@newsgroups.borland.com...

> Here is the TestEventsImplImpl.cpp File as modified to add your code:

You are going about it all wrong.  Your Trigger() code should not be using
the TThreadList at all, unless you want clients to broadcast events to other
clients.  The rest of the server code should be using the TThreadList to
reach the Fire_...() methods for each individual client.

Try this code instead:

    class ATL_NO_VTABLE TTestEventsImplImpl :
        public CComObjectRootEx<CComSingleThreadModel>,
        public CComCoClass<TTestEventsImplImpl, &CLSID_TestEventsImpl>,
        public IConnectionPointContainerImpl<TTestEventsImplImpl>,
        public TEvents_TestEventsImpl<TTestEventsImplImpl>,
        public IDispatchImpl<ITestEventsImpl, &IID_ITestEventsImpl,
&LIBID_TestEventsTypeLib>
    {
    public:
        static TThreadList* InterfaceList;

        TTestEventsImplImpl();
        ~TTestEventsImplImpl();

        // Data used when registering Object
        //
        DECLARE_THREADING_MODEL(otApartment);
        DECLARE_PROGID("TestEventsTypeLib.TestEventsImpl");
        DECLARE_DESCRIPTION("");

        // Function invoked to (un)register object
        //
        static HRESULT WINAPI UpdateRegistry(BOOL bRegister)
        {
            TTypedComServerRegistrarT<TTestEventsImplImpl>
                regObj(GetObjectCLSID(), GetProgID(), GetDescription());
            return regObj.UpdateRegistry(bRegister);
        }

        BEGIN_COM_MAP(TTestEventsImplImpl)
            COM_INTERFACE_ENTRY(ITestEventsImpl)
            COM_INTERFACE_ENTRY2(IDispatch, ITestEventsImpl)
            COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)
        END_COM_MAP()

        BEGIN_CONNECTION_POINT_MAP(TTestEventsImplImpl)
            CONNECTION_POINT_ENTRY(DIID_ITestEventsImplEvents)
        END_CONNECTION_POINT_MAP()

    public:
        static void TriggerOnAllClients();

    // ITestEventsImpl
    public:
        STDMETHOD(Trigger());
    };


    TThreadList* TTestEventsImplImpl::InterfaceList = NULL;

    TTestEventsImplImpl::TTestEventsImplImpl()
    {
        if( !InterfaceList )
            InterfaceList = new TThreadList;
        if( InterfaceList )
            InterfaceList->Add(this);
    }

    TTestEventsImplImpl::~TTestEventsImplImpl()
    {
        if( InterfaceList )
        {
            int count;

            TList *list = InterfaceList->LockList();
            try
            {
                list->Remove(this);
                count = list->Count;
            }
            __finally {
                InterfaceList->UnlockList();
            }

            if( count < 1 )
            {
                delete InterfaceList;
                InterfaceList = NULL;
            }
        }
    }

    void TTestEventsImplImpl::TriggerOnAllClients()
    {
        if( InterfaceList )
        {
            TList *list = InterfaceList->LockList();
            try
            {
                for(int x = 0; x < list->Count; ++x)
                {
                    try
                    {
                        TTestEventsImplImpl *pIntf = (TTestEventsImplImpl *)
list->Items[x];
                        if( pIntf )
                            pIntf->Trigger();
                    }
                    catch(...) { }
                }
            }
            __finally {
                InterfaceList->UnlockList();
            }
        }
    }

    STDMETHODIMP TTestEventsImplImpl::Trigger()
    {
        WideString strName(L"Whatever");
        Fire_Event1(strName);
        return S_OK;
    }


You can then do the following where desired in the server code:

    void TCOMServerCode::DoSomething()
    {
        // ...
        if( something happened )
            TTestEventsImplImpl::TriggerOnAllClients();
        // ...
    }


Gambit
Re: sockets????
#3135
Author: Gary D
Date: Wed, 02 Nov 2005 11:26
37 lines
2295 bytes
I heard the heavenly choir sing this morning, from the server side.

Thanks,
Now that I have a working model I will be able to pick it apart and learn 
how it works.
For one thing I have never seen this done as a means of executing a 
function:

TTestEventsImplImpl::TriggerOnAllClients();

All I have ever seen is stuff like this:

TTestEventsImplImpl->TriggerOnAllClients();

TTestEventsImplImpl.TriggerOnAllClients();

What are the differences between the 3 if it isn't to involved to explain?

Gary


"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message 
news:43688124$1@newsgroups.borland.com...
>
> "Gary D" <gcdesroches@nctc.com> wrote in message
> news:4367f76b@newsgroups.borland.com...
>
>>     TestEventsImplImpl->Trigger();
>> This gets an access violation when executed
>
> Of course it does.  You are calling Trigger() on an uninitialized pointer.
> You have not instantiated the TestEventsImplImpl class at all.
>
>
> Gambit
>
> 
Re: sockets????
#3136
Author: Remy Lebeau (TeamB)
Date: Wed, 02 Nov 2005 18:21
22 lines
2162 bytes
"Gary D" <gcdesroches@nctc.com> wrote in message
news:4368a28c$1@newsgroups.borland.com...

> For one thing I have never seen this done as a means of
> executing a function:
>
> TTestEventsImplImpl::TriggerOnAllClients();

TriggerOnAllClients() is declared as a 'static' method.  That allows it to
be called using just the class type without any pointer to an instance of
the class.

> What are the differences between the 3 if it isn't to involved to explain?

The '->' and '.' operators operate on class instances.  The '.' operator can
only be invoked on the memory of an object instance directly, whereas the
'->' operator is invoked on a pointer to an object instance (or an object
that overrides the '->' operator, but that is a separate issue).


Gambit
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads