Verification Of User's Existence In Chat Script
Solution 1:
As promised, here are some classes used in implementing long-polling. There are basically 6 classes (see below). Some of these classes may end-up being unneeded for YOUR purposes, but they made sense for mine. These have "mostly" been sanitized for you.
- Controller: Processes actions required to create a valid response (db operations etc.)
- Processor: Manages asynch communication with the web page (itself)
- IAsynchProcessor: The service processes instances that implement this interface
- Sevice: Processes request objects that implement IAsynchProcessor
- Request: The IAsynchProcessor wrapper containing your response (object)
- Response: Contains custom objects or fields
If you need help with the JavaScript or HTML add-in a comment below...I will write something for you.
HTTP HANDLERS:
using System;
using System.Configuration;
using System.Web;
using System.Web.Script.Serialization;
using System.Web.Services;
using System.Web.SessionState;
namespaceConcept.LongPolling.Handlers
{
///<summary>/// Summary description for Controller///</summary>publicclassController : IHttpHandler, IReadOnlySessionState
{
#region CONSTRUCTORS#endregion#region PROPERTIES///<summary>Gets a Boolean value indicating that another request can use the current instance of the DefaultHttpHandler class.</summary>///<remarks>Returning true makes the same AsyncHttpHandler object be used for all requests.</remarks>///<remarks>Returning false here makes ASP.Net create object per request.</remarks>publicbool IsReusable { get { returntrue; } }
#endregion#region METHODS///<summary>Enables synchronous processing of HTTP Web requests</summary>///<param name="context">An HttpContext object that provides references to the intrinsic server objects</param>//////<remarks>This is where you would send commands to the controller that would affect processing in some manner.</remarks>publicvoidProcessRequest(HttpContext context)
{
thrownew NotImplementedException();
}
///<summary>Creates the response object which is serialized back to the client</summary>///<param name="response"></param>publicstatic Response CreateResponse(Response response)
{
try
{
response.Generate();
}
catch (System.Exception ex)
{
response.SessionValid = false;
}
return response;
}
#endregion
}
}
using System;
using System.Configuration;
using System.Web;
using System.Web.Script.Serialization;
using System.Web.Services;
using System.Web.SessionState;
using Concept.LongPolling.LongPolling;
namespaceConcept.LongPolling.Handlers
{
///<summary>/// Summary description for Processor///</summary>publicclassProcessor : IHttpHandler, IHttpAsyncHandler, IReadOnlySessionState
{
#region CONSTRUCTORS#endregion#region PROPERTIES///<summary>Gets a Boolean value indicating that another request can use the current instance of the DefaultHttpHandler class.</summary>///<remarks>Returning true makes the same AsyncHttpHandler object be used for all requests.</remarks>///<remarks>Returning false here makes ASP.Net create object per request.</remarks>publicbool IsReusable { get { returnfalse; } }
#endregion#region METHODS///<summary>Enables synchronous processing of HTTP Web requests</summary>///<param name="context">An HttpContext object that provides references to the intrinsic server objects</param>publicvoidProcessRequest(HttpContext context)
{
thrownew NotImplementedException();
}
#region IHttpAsyncHandler Members///<summary>Enables asynchronous processing of HTTP Web requests</summary>///<param name="context">An HttpContext object that provides references to the intrinsic server objects</param>///<param name="cb">The method to call when the asynchronous method call is complete. If callback is null, the delegate is not called.</param>///<param name="extraData"></param>///<returns>Any state data that is needed to process the request.</returns>public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
Int32 someValueYouLikeToSendInYourClass = Convert.ToInt32(context.Request["Number"]);
Request request = new Request(cb, context);
request.Response.Number = someValueYouLikeToSendInYourClass;
Service.Singleton.AddRequest(request);
return request;
}
///<summary>Provides an end method for an asynchronous process.</summary>///<param name="result">An object that contains information about the status of the process.</param>publicvoidEndProcessRequest(IAsyncResult result)
{
Request request = result as Request;
JavaScriptSerializer serializer = new JavaScriptSerializer();
request.HttpContext.Response.ContentType = "text/json";
request.HttpContext.Response.Write(serializer.Serialize(request.Response));
request.HttpContext.Response.End();
}
#endregion#endregion
}
}
SUPPORTING CLASSES:
using System;
using System.Runtime.InteropServices;
namespaceConcept.LongPolling.LongPolling
{
///<summary>Represents the executable instance of an asynchronous operation.</summary>
[ComVisible(true)]
publicinterfaceIAsynchProcessor : IAsyncResult
{
///<summary>/// Gets a value that indicates whether the operation completed sucessfully.///</summary>///<returns>true if the operation completed sucessfully; otherwise, false.</returns>boolProcessRequest();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Threading;
namespaceConcept.LongPolling.LongPolling
{
publicclassService
{
#region CONSTRUCTORSprivateService()
{
requests = new List<IAsynchProcessor>();
backgroundThread = new Thread(new ThreadStart(MainLoop));
backgroundThread.IsBackground = true;
backgroundThread.Start();
}
#endregion#region PROPERTIESstaticreadonlyobject _padlock = newobject();
privatestatic Service singleton;
private Thread backgroundThread;
private List<IAsynchProcessor> requests;
publicstatic Service Singleton
{
get
{
lock (_padlock)
{
if (_singleton == null)
_singleton = new Service();
return _singleton;
}
}
}
#endregion#region METHODSprivatevoidMainLoop()
{
while (true)
{
foreach (IAsynchProcessor request in requests.ToArray())
{
if (request.ProcessRequest())
requests.Remove(request);
}
Thread.Sleep(500);
}
}
publicvoidAddRequest(IAsynchProcessor request)
{
requests.Add(request);
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Concept.LongPolling.Business;
using System.Data;
namespaceConcept.LongPolling.Handlers
{
publicclassResponse
{
#region CONSTRUCTORSpublicResponse()
{
SessionValid = true;
Exception = String.Empty;
}
#endregion#region PROPERTIESpublicconstint TimeOffset = 120;
public Int32 Number { get; set; }
publicbool SessionValid { get; set; }
public String Exception { get; set; }
#endregion#region METHODSpublicvoidGenerate()
{
// do some desired operation
Number += 1;
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Concept.LongPolling.LongPolling;
namespaceConcept.LongPolling.Handlers
{
publicclassRequest : IAsynchProcessor
{
#region CONSTRUCTORSpublicRequest(AsyncCallback callback, HttpContext context)
{
asyncCallback = callback;
httpContext = context;
createdTime = DateTime.Now;
Response = new Response();
}
#endregion#region PROPERTIESpublicconstint TimeoutSeconds = 15;
private AsyncCallback asyncCallback;
private HttpContext httpContext;
private DateTime createdTime;
publicbool TimedOut
{
get
{
return ((DateTime.Now - createdTime).TotalSeconds >= TimeoutSeconds);
}
}
public Response Response { get; set; }
#region IAsyncResult Memberspublic HttpContext HttpContext
{
get
{
return httpContext;
}
}
publicobject AsyncState { get; set; }
System.Threading.WaitHandle IAsyncResult.AsyncWaitHandle
{
get { thrownew NotImplementedException(); }
}
bool IAsyncResult.CompletedSynchronously
{
get { returnfalse; }
}
publicbool IsCompleted
{
get { return isCompleted; }
set
{
if (!value) return;
this.isCompleted = true;
asyncCallback(this);
}
}
bool isCompleted = false;
#endregion#endregion#region METHODSpublicboolProcessRequest()
{
this.Response = Controller.CreateResponse(this.Response);
this.IsCompleted = true;
returnthis.IsCompleted;
}
#endregion
}
}
Solution 2:
Just have your JavaScript chat code send a message to the server every 2 seconds using XMLHttpRequest. When you don't receive a message, that means that the user has closed the window.
Solution 3:
The chat can send a logout message using the onunload
event, which is triggered if the user leaves the page/closes the browser, however it is not reliable. A second option for the server is to begin a timeout countdown as soon as the underlying TCP connection is closed and show the user as "offline" in case he does not reconnect in time.
Post a Comment for "Verification Of User's Existence In Chat Script"