|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionI ran into the problem of creating a chat room where two users can chat directly. I didn't like the idea of using server side code and doing all these post back which is not user friendly. I found that with the use of remote scripting, we can make a simple and fast chat application. BackgroundI built this application using the Remote Scripting client and server side implementation provided by Alvaro Mendez: Remote Scripting. I also used some chat room logic from Julien Couvreur. Code WalkthroughI'll start by examining the ChatEngine.cs file which contains all the logic. You'll find four classes in this file:
Other operations in the class include creating new rooms and deleting the empty chat rooms. Building The ApplicationI will build a simple app to demonstrate the usage of the Chat Engine classes. First, we create a simple page (default.aspx) where the user can enter his nickname (which is saved in the session). After that, the user enters the nickname of the other user he wants to chat with. The two user names are used to create the ID of the chat room. Then the user is redirected to chat.aspx with the name of the other passed in the query string and saved in a hidden variable. In Chat.aspx, a chat room is created for the two users: private void Page_Load(object sender, System.EventArgs e)
{
if (AMS.Web.RemoteScripting.InvokeMethod(this))
//if this is a callback function return
return;
txtMsg.Attributes.Add("onkeypress", "return clickButton(event,'btn')");
if (!IsPostBack)
{
if (Request.QueryString["userid"]!=null
&& Request.QueryString["userid"]!="")
{
otherUser.Value=Request.QueryString["userid"];
ChatRoom room=ChatEngine.GetRoom(Session["UserName"].ToString() ,
Request.QueryString["userid"]);
string s=room.JoinRoom(Session["UserName"].ToString(),
Session["UserName"].ToString() );
txt.InnerText=s;
string strScript="< script >startTimer();< /script >";
this.RegisterClientScriptBlock("timerScript",strScript);
}
else
{
Response.Write("User id Missing");
}
}
}
On the client side, remote scripting is used to send messages to the chat room. Using Alvaro Mendez's implementation, calling server functions from the client is very simple. For example, when the user clicks the Enter key in the text box, a message is sent to the chat room using the following script: //Chat.aspx
function clickButton(e, buttonid)
{
var bt = document.getElementById(buttonid);
if (typeof bt == 'object')
{
if(navigator.appName.indexOf("Netscape")>(-1)){
if (e.keyCode == 13)
{
bt.click();
return false;
}
}
if (navigator.appName.indexOf("Microsoft Internet Explorer")>(-1))
{
if (event.keyCode == 13)
{
bt.click();
return false;
}
}
}
}
function button_clicked()
{
RS.Execute("Chat.aspx", "SendMessage",document.Form1.txtMsg.value,
document.Form1.otherUser.value, callback, errorCallback);
document.Form1.txtMsg.value="";
document.Form1.txt.scrollIntoView("true");
}
function callback(result)
{
document.Form1.txt.value=document.Form1.txt.value+result;
document.Form1.txt.doScroll();
}
function errorCallback(result)
{
alert("An error occurred while invoking the remote method: "
+ result);
}
The //Chat.aspx.cs
public string SendMessage(string msg,string toUserID)
{
try
{
ChatRoom room=ChatEngine.GetRoom(Session["UserName"].ToString() ,toUserID);
string res="";
if (room!=null)
{
res=room.SendMessage(msg,Session["UserName"].ToString() ,toUserID);
}
return res;
}
catch(Exception ex)
{
}
return "";
}
As you can see, The user can leave the room by clicking the Exit button. private void btnExit_Click(object sender, System.EventArgs e)
{
try
{
ChatRoom room=ChatEngine.GetRoom(Session["UserName"].ToString(),
Request.QueryString["userid"]);
room.LeaveRoom(Session["UserName"].ToString() );
Response.Redirect("default.aspx");
}
catch(Exception ex)
{
}
}
I also added a client side function that handles the //Chat.aspx
function Leave()
{
RS.Execute("Chat.aspx", "LeaveRoom",document.Form1.otherUser.value);
}//Chat.aspx.cs
public string LeaveRoom(string otherUser)
{
try
{
ChatRoom room=ChatEngine.GetRoom(Session["UserName"].ToString() ,otherUser);
if (room!=null)
room.LeaveRoom(Session["UserName"].ToString() );
}
catch(Exception ex)
{
}
return "";
}
Remaining is to periodically update the client to receive the messages sent from the other user. A simple solution is to add a timer that makes a remote call to the server function. //Chat.aspx
var interval = "";
var i = 5;
function startTimer()
{
interval = window.setInterval("tTimer()",1000);
}
function stopTimer()
{
window.clearInterval (interval);
interval="";
}
function tTimer()
{
RS.Execute("Chat.aspx", "UpdateUser",document.Form1.otherUser.value,
callback, errorCallback);
}//Chat.aspx.cs
public string UpdateUser(string otherUserID)
{
try
{
ChatRoom room=ChatEngine.GetRoom(Session["UserName"].ToString() ,
otherUserID);
if (room!=null)
{
string res="";
if (room!=null)
{
res=room.UpdateUser(Session["UserName"].ToString());
}
return res;
}
}
catch(Exception ex)
{
}
return "";
}
A timer is added on the server to periodically clean and remove the empty chat rooms. //Global.asax.cs
Timer ChatRoomsCleanerTimer=new System.Threading.Timer(
new TimerCallback(ChatEngine.CleanChatRooms),null,3600000,3600000);//ChatEngine.cs
public static void CleanChatRooms(object state)
{
Monitor.Enter(Rooms);
foreach(object key in Rooms.Keys)
{
ChatRoom room=(ChatRoom)Rooms[key.ToString()];
room.ExpireUsers(100);
if (room.IsEmpty())
{
room.Dispose();
Rooms.Remove(key.ToString());
}
}
Monitor.Exit(Rooms);
}
Points of InterestYou can easily extend the
|
||||||||||||||||||||||