<script type="text/javascript">
function Keepline() {
var da = { Action: "Keepline",userId:$("#userid").val() };
$.ajax({
type: 'POST',
url: "@Url.Content("~")comet_broadcast.asyn",
data: da,
dataType: 'json',
success: function (data, status) {
//debugger;
//if (data.ResponseStatus == 1) {
// alert(1);
//}
$("#maxPrice").html(data);
Keepline();
},
error: function (XMLHttpRequest, errorinfo, er) {
// debugger;
// alert(2);
},
complete: function (XHR, TS) {
//debugger;
//alert(3);
}
});
}
function BaoJia() {
var sData = { Action: "GetMaxBaoJia", userId: $("#userid").val(), price: $("#txt_price").val() };
$.ajax({
type: 'POST',
url: "@Url.Content("~")comet_broadcast.asyn",
data: sData,
dataType: 'json',
success: function (data, status) {
$("#maxPrice").html(data);
},
error: function (XMLHttpRequest, errorinfo, er) {
//debugger;
// alert(2);
},
complete: function (XHR, TS) {
//debugger;
//alert(3);
}
});
}
</script>
<body>
先加入后再报价<br />
用户: <input type="text" id="userid"/> <input type="button" value="加入" οnclick="Keepline()" /><br />
<input type="button" value="报价" οnclick="BaoJia()" /><br />
<input type="text" id="txt_price"/><br />
当前最高报价: <div id="maxPrice">0</div>
</body>
</html>
system.web下 加配置
<httpHandlers>
<!--comet长连接配置字节-->
<add verb="*" path="comet_broadcast.asyn" type="ServerPushHttpHandler.ServerPush,ServerPushHttpHandler"/>
</httpHandlers>
RouteConfig 中加
routes.IgnoreRoute("{resource}.asyn/{*pathInfo}");
/// <summary>
/// 演示服务推送的界面
/// </summary>
/// <returns></returns>
public ActionResult Demo_Server_Push()
{
return View();
}
新增一个类库 ServerPushHttpHandler
新增三个类
public class ServerPush : IHttpAsyncHandler
{
#region IHttpAsyncHandler 成员
//启用对HTTP处理程序的异步调用
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
return new ServerPushHandler(context, new ServerPushResult(context, cb, extraData)).ExecAction();
}
//进程结束时提供异步处理 End 方法。
public void EndProcessRequest(IAsyncResult result)
{
}
#endregion
#region IHttpHandler 成员(IHttpAsyncHandler同时继承于IHttpHandler)
//获取一个值,该值指示其他请求是否可以使用 IHttpHandler 实例。 (继承自 IHttpHandler。)
public bool IsReusable
{
get { return false; ; }
}
//通过实现 IHttpHandler 接口的自定义 HttpHandler 启用 HTTP Web 请求的处理。 (继承自 IHttpHandler。)
public void ProcessRequest(HttpContext context)
{
throw new NotImplementedException();
}
#endregion
}
public class ServerPushHandler
{
#region 全局变量
HttpContext m_Context;
//推送结果
ServerPushResult _IAsyncResult;
//声明一个集合
static Dictionary<string, ServerPushResult> dict = new Dictionary<string, ServerPushResult>();
static int tempMaxBaoJia=0;//临时最高报价
#endregion
#region 构造函数
/// <summary>
/// 构造方法
/// </summary>
public ServerPushHandler(HttpContext context, ServerPushResult _IAsyncResult)
{
this.m_Context = context;
this._IAsyncResult = _IAsyncResult;
}
#endregion
#region 执行操作
/// <summary>
/// 根据Action判断执行方法
/// </summary>
/// <returns></returns>
public ServerPushResult ExecAction()
{
var userid = m_Context.Request["userId"];
switch (m_Context.Request["Action"])
{
case "GetMaxBaoJia":
var price =Convert.ToInt32(m_Context.Request["price"]);
GetMaxBaoJia(userid,price);
break;
case "Keepline":
Keepline(userid);
break;
default:
break;
}
return _IAsyncResult;
}
#endregion
#region 保持联接
private void Keepline(string userId)
{
if (!dict.ContainsKey(userId))
dict.Add(userId, _IAsyncResult);
else //登录时虽然保存了当前用户的连接,但是登录完后异步向客户端推送了数据,此时这个客户端连接已经失效,那么在connect时相当于才是此客户端与服务器端真正的连接,需要重新更新ServerPushResult的值
dict[userId] = _IAsyncResult;
}
#endregion
#region
/// <summary>
/// 获取最大报价
/// </summary>
/// <param name="userid"></param>
/// <param name="price"></param>
private void GetMaxBaoJia(string userId,int price)
{
if (price>tempMaxBaoJia)
{
tempMaxBaoJia = price;
}
_IAsyncResult.Result = Json(tempMaxBaoJia);
foreach (var item in dict.Keys)
{
dict[item].Result = Json(tempMaxBaoJia);
dict[item].Send();
}
//_IAsyncResult.Send();
}
#endregion
/// <summary>
/// 将对象转换成json字符串
/// </summary>
/// <param name="obj">对象</param>
/// <param name="dateFormat">对象中日期要转换的格式</param>
/// <returns></returns>
public static String Json(object obj, String dateFormat = "yyyy-MM-dd")
{
IsoDateTimeConverter timeConverter = new IsoDateTimeConverter();
timeConverter.DateTimeFormat = dateFormat;
var jSetting = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, Converters = { timeConverter } };
var strjson = JsonConvert.SerializeObject(obj, Newtonsoft.Json.Formatting.Indented, jSetting);
strjson = Regex.Replace(strjson, @"\\/Date\((\d+)\)\\/", match =>
{
DateTime dt = new DateTime(1970, 1, 1);
dt = dt.AddMilliseconds(long.Parse(match.Groups[1].Value));
dt = dt.ToLocalTime();
return dt.ToString(dateFormat);
});
return strjson;
}
}
public class ServerPushResult : IAsyncResult
{
#region 全局变量
HttpContext m_Context;
AsyncCallback m_Callback;
object m_ExtraData;
bool m_IsCompleted = false;
public string Result { get; set; }
#endregion
#region 构造函数
/// <summary>
/// 构造函数
/// </summary>
/// <param name="context"></param>
/// <param name="cb"></param>
/// <param name="extraData"></param>
public ServerPushResult(HttpContext context, AsyncCallback cb, object extraData)
{
m_Context = context;
m_Callback = cb;
m_ExtraData = extraData;
}
#endregion
#region 向客户端发送消息
/// <summary>
/// 向客户端响应消息
/// </summary>
/// <param name="result">结果信息</param>
public void Send()
{
try
{
m_Context.Response.Write(Result);
if (m_Callback != null)
{
m_Callback(this);
}
}
catch { }
finally
{
m_IsCompleted = true;
}
}
#endregion
#region IAsyncResult 成员
//获取用户定义的对象,它限定或包含关于异步操作的信息。
public object AsyncState
{
get { return null; }
}
//获取用于等待异步操作完成的 WaitHandle。
public WaitHandle AsyncWaitHandle
{
get { return null; }
}
//获取异步操作是否同步完成的指示。
public bool CompletedSynchronously
{
get { return false; }
}
//获取异步操作是否已完成的指示。
public bool IsCompleted
{
get { return m_IsCompleted; }
}
#endregion
}
需要引用json的dllnewtonsoft.json.dll 自己网上找 因为前台规定返回是json,所以返回时需要json一下,要不然有些数据前台转换会有问题。
其实思路很简单
就是keepline发起一个 长连接 在等待 。 多个客户端,其中一个客户端 触发一个事件,后台就推送所有 消息 返回 给在等待长连接的其他客户端。
欢迎转载,尊重劳动成果,请标明出处。
本文参考http://www.cnblogs.com/zengqinglei/archive/2013/03/31/2991189.html
http://www.ibm.com/developerworks/cn/web/wa-lo-comet/