Archive for Messaging
JUICE chat (Stratus Peer to Peer)
Posted by: | CommentsOne of my ongoing weekend projects is an AIR chat application, recently rechristened “JUICE” a.k.a. “John’s Ultimate Internet Chat Experience”. I realize that may only be the case for myself, but the project has been very educational and entertaining for me.
The initial release used AIR/Flex as the front-end, ColdFusion and MySQL for the backend, and BlazeDS messaging for message transmission and “peer discovery”. I worked on it over a couple weeks adding features like encryption, toast-style notifications, as well as a few other less notable things.
I knew the architecture was awful and would never scale beyond a couple hundred users (if that many). Here’s the basics of how it worked:
- The user would login, ColdFusion/MySQL would send back a list of chat buddies.
- Each logged in user would ping the messaging server every 10-30 seconds to announce “I’m still here!”
- The pings would be broadcast to everyone logged in (and connected to the messaging server). The application would filter out the ones it was interested in based on user id.
- Sending messages worked similarly, the user would send the message (which included information about the intended recipient), which would then be broadcast to EVERYONE.
- Everyone would filter this information, and the recipient would know it was for him, and would display it.
You can see why this would not scale well, the amount of traffic and pinging going on. Eventually even a user with only 1 or 2 buddies would notice a significant drop in performance as the number of total users increased. There are some applications of “chat” for which BlazeDS messaging and polling is well suited for (like a chat room). A chat application involving “buddies” is much better suited for P2P.
Enter Stratus. I discovered Stratus a few months ago but was unwilling to delve into it on account of my hectic schedule. Fortunately one of my friends went and did all the dirty work figuring out how to get it up and running (turns out it’s pretty easy) and I was able to apply it to my chat client.
I’m very pleased with the results, though it’s still very much a work in progress. I’ve even been able to add video and voice chat features, which is why I went through the trouble in the first place. Here is how my peer discovery mechanism operates. It requires only 3 calls to the server per client (which I could easily condense to 2 if I wanted).
- The user logs in.
- If the user successfully authenticated, he connects to Stratus and receives his peer ID.
- The user updates his peer ID in the database (which was set to 0) and gets a list of his buddies and their peer IDs. I also update information like whether or not I have a camera/mic.
- The user processes his buddy. If the peer ID is something other than 0, then I know this buddy logged in before me, so I must send him my peer ID.
- Any buddies that have a peer ID of 0 are not logged in, I need to listen for them though since they will get my peer ID when they log in.
- When I log out or close the application, I call the server and reset my peer ID to 0. I also notify all of my connected peers I’m logging out.
There are a few more steps in the process, but it decreases the load on the server significantly, transferring the “burden of proof” onto the clients.
Interesting to note is the way I get the peer ID of a client who connects after me (step 4). I don’t actually have to make a call for this, rather he simply has to start broadcasting to me on the NetStream I set up to listen for him (step 5). When the connection is made, an event will be dispatched by the NetStream class. In fact, 3 events will be fired, I just chose to act on one of them.
The peer ID can be obtained from the peerStreams array on the publishing NetStream. I then use that information to set up my subscribing NetSream.
if (this.peerId == null || this.peerId == "0") {
this.peerId = publishNetStream.peerStreams[0].farID;
this.subscribeNetStream = new NetStream(model.netConnection, this.peerId);
this.subscribeNetStream.client = new NetStreamClient();
this.subscribeNetStream.play(streamName);
}
Anyway,I’m planning on doing another post to outline my video and voice handshake protocols. They’re nothing to write home about, but I’d love some feedback if there’s a better way. I’m also planning on releasing JUICE after I bring it’s level of functionality back up to where the original version was, so stay tuned and you should see my install badge at the bottom of my blog.
Messaging with Flex/ColdFusion via BlazeDS : Part 1 (CF configuration)
Posted by: | CommentsI just went through setting up Flex / ColdFusion messaging via BlazeDS, and have come through it rather unscarred considering it’s my first time using Flex messaging. Most of the documentation I have regarding messaging is biased toward Java (including the sample apps included with BlazeDS). A lot of what I found online, though very helpful, didn’t really apply to the way I wanted to do it. I’m going to document some of the steps here in the hopes that it may be helpful for others (2 parts).
Here are a few details about my configuration that may help you determine if this post might be helpful to you.
- When I create a new Flex project, I always leave the “Application server type” set to “None”. This helps me to create applications that can be used against multiple server types.
- My ColdFusion server isn’t running on the same server I develop on, nor is it usually the same server I serve my production SWFs from.
- This assumes you have BlazeDS correctly set up with ColdFusion, and all of your configuration files (messaging/proxy/remoting/service-config.xml) roughly the same as the default ones included in the BlazeDS distribution (note: there are special ones included for ColdFusion).. If you need help installing and configuring BlazeDS with CF, go here: http://labs.adobe.com/wiki/index.php/BlazeDS:Release_Notes .
- I will be going through 2 scenarios on the client side. First, is a standard publish/subscribe setup, where the clients publish and subscribe. Second, a situation where the client only subscribes, relying on the server to do all the publishing.
- I don’t maintain any of the above mentioned configuration files in the project, electing to manually instantiate my channels/channel sets in ActionScript.
Setting up services-config.xml
The services-config.xml file already contains a channel definition named “cf-polling-amf”. It can be used as-is if you want your poll interval to be 8 seconds. To change it, set the <polling-interval-seconds> tag to the desired interval.
Setting up messaging-config.xml
Next open the messaging-config.xml file. Here is where you set up your adapters and destinations. If the line isn’t included under the <adapters> tag, you will need to add it”
<adapter-definition id="cfgateway" class="coldfusion.flex.CFEventGatewayAdapter" default="true" />
The default destination “ColdFusionGateway” as configured is sufficient for this post. If you set up your own, there are three tags you will need to define:
- <adapter>, this should refer to the adapters defined in messaging-config.xml, usually set to cfgateway.
- <gatewayid>, this can be set as a wildcard (*) meaning the client will define it, or you can set it to a specific gatewayid (which I will explain how to set up shortly)
- <channel>, which refers to one of the channels defined in services-config.xml, in this case “cf-polling-amf”.
Setting up a gateway CFC
An event gateway is tied to a specific CFC file, and is configured in the ColdFusion administrator. First we will set up two CFC classes. One will be used in our client-broadcast/subscribe setup, the other in the server-broadcast/client-subscribe setup.
The basic client-broadcast/subscribe CFC should look like the following:
<cfcomponent output="false">
<cffunction name="onIncomingMessage" access="remote" returntype="struct">
<cfargument name="event" type="struct" required="true"/>
<cfreturn event.data />
</cffunction>
</cfcomponent>
It’s important that it has that name, and accepts and returns a struct-type. It’s perfectly OK to process the headers or do whatever it is you need to do before the return value is broadcast.
The server-broadcast/subscribe CFC should look like the following:
<cfcomponent output="false"> </cfcomponent>
Complicated, I know, but try not to cry…
Setting up the event gateway
Login to your ColdFusion Administrator and expand the “Event Gateways” tab. From the menu select “Gateway Instances”. Fill in the following fields:
- GatewayID. You will use this either in your messaging-config.xml, and/or in your Flex application.
- Gateway Type. Select “Data Services Messaging”. It should be there if BlazeDS is set up correctly with ColdFusion.
- CFC Path. Enter or browse to the absolute path of the CFC that will handle this gateway’s requests.
Since we’re using the messaging-config.xml, there’s no need to select a configuration file; and leave the startup mode to auto. If you created both CFCs as described above, then you will need to configure a separate gateway instance for each of them.
Once you restart the server, ColdFusion is set up for messaging.
Continued in part two: Messaging with Flex/ColdFusion via BlazeDS: Part 2 (Flex configuration)

