[muscle] Re: peer-to-peer help intro

  • From: "Jeremy Friesner" <jaf@xxxxxxxxxxxx>
  • To: muscle@xxxxxxxxxxxxx
  • Date: Sun, 01 May 2005 00:56:35 PDT (-0700)

Hi Barry,

> Thanks for the fast reply Jeremy!  

Sure thing :^)
> I am writing in C++ and though I learned it in
> university, it's been quite a number of years since
> I've touched it.  I'm writing for Win32, and for my
> first project I want to do a simple chat app
> (peer-to-peer) where the IP addresses of both chat
> clients are already known.

So you are envisioning a text-chat application where it's always two people 
chatting with each other=3F

> So I looked at BeShareAndMuscle.html and based on
> that, viewed class Win32MessageTransceiverThread from
> the API.  It seems method AddNewConnectSession() will
> connect to the IP and port of the other MUSCLE client
> I want to do peer-to-peer with 

Assuming you do want the directly-connected 2-person model (i.e. with no server 
involved), then the above is half of the process.  The other part of the 
equation is that when User A does an AddNewConnectSession() to initiate the TCP 
connection to User B, User B has to be already listening for that incoming TCP 
connection. (otherwise the TCP connection will be refused by User B's operating 

The simplest way to implement the listening-for-incoming-connections part is to 
have your program create (and run, via StartInternalThread()) an 
AcceptSocketsThread object at startup.  That way, when someone tries to connect 
to your computer, the AcceptSocketsThread will accept the TCP connection, and 
send your main thread a Message containing the new connection's TCP socket, 
which you can then pass to MessageTransceiverThread::AddNewSession(int).  At 
that point the TCP connection between the two computers' 
MessageTransceiverThread objects will be ready for use.

But note that the above technique is actually a bit harder to get working than 
the client/server model of just having both clients connect to a muscled server 
and send Messages to each other through it -- so you might want to consider 
just running muscled somewhere and having both clients connect to muscled, 
instead of trying to connect them directly to each other.  Other advantages of 
using muscled as an intermediary include:  the clients don't have to know each 
others' IP addresses in advance, and you can have more than 2 clients 
interacting with each other.

> then I can get any
> messages by looping for events through
> GetNextEventFromInternalThread().
> The event code will
> tell me whether I have a Message object. 

That is correct.

> For sending
> messages, plainTextClient.cpp shows a method
> "sendOutgoingMessage()" of MessageTransceiverThread
> but I can't find that in the API.  What do I do to
> send a message=3F

I think the method you are looking for is 

status=5Ft MessageTransceiverThread::SendMessageToSessions(MessageRef myMsg, 

> For what I want to do, I can't believe it's this easy.
> One fundamental question I have is, is the same code
> used for peer-to-peer as for client-server using
> muscled=3F  That is, instead of connecting directly to
> your client in peer-to-peer, connect instead to the
> server, pattern-match nodes for who to send to, but
> then get or send messages in the same way.  Is that
> right=3F

Yes, that is correct, the same *MessageTransceiverThread classes can be used to 
connect to muscled or to other clients.  (Note, however, that pattern matching 
and all the various PR=5FCOMMAND=5F* stuff is only done by the server code -- 
so if you do a direct client-to-client connection you will get the ability to 
send and receive Messages to each other verbatim, but not any of the 
subscription or pattern-matching features)
> What about client-server with subscriptions=3F  The
> Beginner's guide mentions how to set one up, but
> doesn't mention how to subscribe.

Subscribing is just a matter of sending a PR=5FCOMMAND=5FSETPARAMETERS Message 
to the muscled server with the proper field(s) in it... specifically, any field 
whose fieldname starts with the magic prefix "SUBSCRIBE:" followed by the path 
you want to subscribe to.  As soon as the server receives the 
PR=5FCOMMAND=5FSETPARAMETERS Message, it will start sending you notifications.

For example, to tell the server to start sending you notifications about what 
other clients are connected:

MessageRef msg =3D GetMessageFromPool(PR=5FCOMMAND=5FSETPARAMETERS);
msg()->AddBool("SUBSCRIBE:/*/*", true);

.. and then the server will start sending you PR=5FRESULT=5FDATAITEMS Messages 
containing the requested information.

> Are there some full samples of peer-to-peer and
> client-server that I can study=3F  I couldn't find any.

Well, BeShare is a full example; it uses client-server for the chat and 
file-searches, and peer-to-peer for the actual file transfer.  But it's perhaps 
too big/complex to be easily understandable, and it only runs under BeOS.  
FoxRabbitCarrot is an example of client/server code (it doesn't do any direct 
peer-to-peer connections though).  It will run under Windows, but it uses Qt 
and not the Win32 API directly (although the difference is minimal -- basically 
it uses a QMessageTransceiverThread instead of a Win32MessageTransceiverThread)

The testreflectclient.cpp program in the muscle/tests folder is an interactive 
command-line client that I use(d) to do quick tests of the muscled server; you
might take a look at that.  Unfortunately it was written to interface to the 
API instead of the Windows one, so it would take a little bit of tweaking to get
it to compile and run under Windows (i.e. replacing the 
with Win32MessageTransceiverThread, replacing the BLooper with the Win32
API equivalent, etc).  

If you want, I can tweak testreflectclient.cpp to run under Windows next week 
(I'm at home right now so I don't have access to a Windows machine).  Then you 
could play around with that as a trivial example app, and use it to get a feel 
as to how things work.


Other related posts: