一般需求推送服务时,都会去第三方拿推送组件,如”极光“,”百度“,”小米"什么的,自己用.net实现推送服务端需要面对很多问题,比如C10K,但是企业内部使用往往用不了10K的链接,有个1K,2K就足够,这个时候完全可以自己实现一个推送服务,这样手机应用就不用走外网了。

使用.net实现推送服务有几个选择

1.是使用WCF 基于TCP的回调-针对.net To .net 端,经过7*24小时测试,2K左右的链接能稳定hold住,参考:http://www.cnblogs.com/wdfrog/p/3924718.html

2.自己使用TcpListener或Socket实现一个长连击服务器,由于推送的信息都很短(长信息只推送信息编号),这样在一个MTU里面就可以完成传输,整体上实现起来也不麻烦 ,最近也做了个,大概加一起就400百来行代码,2K链接已经(实际只要hold住98个用户就好了)稳定运行了6天了。

3.使用Comet Request, 首先Comet Request 采用Asp.net + IIS,整整网页就好了,另外由于IIS应用程序池会定期回收,程序写的烂点也不影响,每天都给你一个新的开始,还有Comet 的实现网上代码很多,还有开源的SignalR可以用.

采用Comet方式的实现

1.服务端,使用IHttpAsyncHandler来Hold住请求,需要根据cookie或QueryString中带的UserId来区分不同的用户

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web; namespace MangoPush.WebComet.Core
{
public class PushAsyncHandle : IHttpAsyncHandler
{
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{ var ar = new PushAsyncResult(context, cb, extraData);
CometRequestMgr.Instance.Add(ar);
return ar;
} public void EndProcessRequest(IAsyncResult result)
{ } public bool IsReusable
{
get { return true; }
} public void ProcessRequest(HttpContext context)
{
throw new NotImplementedException();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Threading; namespace MangoPush.WebComet.Core
{
public class PushAsyncResult:IAsyncResult
{
private static int GId = ; private bool m_IsCompleted = false;
private AsyncCallback Callback = null;
public HttpContext Context;
private Object _AsyncState;
public DateTime AddTime{get;private set;}
public int Id { get; set; } public PushAsyncResult(HttpContext context, AsyncCallback callback, object asyncState)
{
Context = context;
Callback = callback;
_AsyncState = asyncState;
AddTime = DateTime.Now;
Interlocked.Increment(ref GId);
int userId = int.TryParse(Context.Request["UserId"], out userId) ? userId : ;
Id = userId;
if (userId == )
{
Release(JUtil.ToJson(new {Code=-,Msg="未提供UserId" }));
}
}
public void Release(string msg)
{
try
{
try
{
Context.Response.Write(msg);
}
catch { }
if (Callback != null)
{
Callback(this);
}
}
catch { }
finally
{
m_IsCompleted = true;
}
}
public object AsyncState
{
get { return _AsyncState; }
} public System.Threading.WaitHandle AsyncWaitHandle
{
get { return null; }
} public bool CompletedSynchronously
{
get { return false; }
} public bool IsCompleted
{
get { return m_IsCompleted; }
}
}
}
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using System.Web; namespace MangoPush.WebComet.Core
{
public class CometRequestMgr
{ public static readonly CometRequestMgr Instance = new CometRequestMgr();
private ConcurrentDictionary<int, PushAsyncResult> Queue = new ConcurrentDictionary<int, PushAsyncResult>(); private CometRequestMgr()
{
var timer = new System.Timers.Timer();
timer.Interval = * ;
timer.AutoReset = false;
timer.Elapsed += (s, e) =>
{ try
{ var list = Queue.Select(ent => ent.Value).ToList();
#region 清理完成链接
foreach (var it in list)
{
if (it.IsCompleted)
{
try
{
PushAsyncResult c = null;
Queue.TryRemove(it.Id,out c); }
catch (Exception ex)
{ continue;
}
}
}
#endregion }
catch (Exception ex)
{ }
finally
{
timer.Start();
} };
timer.Start(); } public void Add(PushAsyncResult ar)
{
Queue[ar.Id] = ar;
}
public void BroadCastMsg(string msg)
{
msg +="," + DateTime.Now.ToString();
foreach (var c in Queue)
{
try
{ c.Value.Release(JUtil.ToJson( new {Code=,Msg= msg})); }
catch { }
finally
{
PushAsyncResult outIt=null;
Queue.TryRemove(c.Key,out outIt);
}
}
}
}
}

2.网页端,使用ajax方式发起访问,特别注意的是需要设置timeout,这样如果断线或者服务端挂了重启,可以自动修复

    $(function () {

        function long_polling() {
var _url = '/pushService.act?userId=' + $("#userId").val();
console.log(_url); var ajaxRequest = $.ajax({
url: _url, //请求的URL
timeout: 1000 * 60 * 3, //超时时间设置,单位毫秒
type: 'get', //请求方式,get或post
data: {}, //请求所传参数,json格式
dataType: 'json', //返回的数据格式
success: function (data) { //请求成功的回调函数 console.log(data);
if (data.Code == 0) {
$('#msg').append(data.Msg + "<br/>");
}
},
complete: function (XMLHttpRequest, status) { //请求完成后最终执行参数
if (status == 'timeout') {//超时,status还有success,error等值的情况
ajaxRequest.abort();
console.log("超时");
} if ($("#btn").val() == "停止") {
long_polling();
}
}
}); }
$("#btn").click(function () { if ($("#btn").val() == "启动") {
long_polling();
$("#btn").val("停止");
} else {
$("#btn").val("启动");
}
}); $("#btnCls").click(function () {
$("#msg").text("");
}); });

3.Winform端,采用WebClient发起请求,并且使用AutoResetEvent控制超时重连(相当于心跳包)

 private void Do()
{
try
{ while (Enable)
{
Console.WriteLine("发起请求!");
var url = @"http://192.168.9.6:9866/pushService.act?userId=18";
using (var wc = new WebClient())
{
wc.Encoding = Encoding.UTF8;
#region 回调处理
wc.DownloadStringCompleted += (s, e) => { if (e.Error != null)
{
Console.WriteLine(e.Error);
}
else if (e.Cancelled)
{
Console.WriteLine("Be Cancelled!");
}
else
{
Console.WriteLine(e.Result); }
autoReset.Set();
};
#endregion
var uri = new Uri(url);
wc.DownloadStringAsync(uri); var isOK= autoReset.WaitOne(1000 * 60 * 5);
if (!isOK)
{
wc.CancelAsync();
} }
}
}
catch (Exception ex)
{
Console.WriteLine("错误" + ex.Message);
}
finally
{
if (Enable)
{
ThreadPool.QueueUserWorkItem(o => { Do(); }, null);
}
} }

4.Android端

1.类似WinForm端,目前采用AsyncHttpClient,写法跟Js差不多,需要设置timeout

2.由于android会回收进程,需要AlarmManager,定期检查推送服务是否还存活

3.android系统重启,开关网络,调整时间,需要订阅相应广播,调整AlermManager,触发平率。

总结:

整个能支持10K,100K,2000K链接的,挺不容易,但是一般中小企业使用1K,2K甚至0.1K足矣,3,4百行代码就完事,至少可以让员工不用连3G,4G了,NND,提速降价,也不知道降那去了。

最后整2个图片

asp.net 中长尾链接实现推送 -- comet的更多相关文章

  1. 在 Asp.NET MVC 中使用 SignalR 实现推送功能 [转]

    在 Asp.NET MVC 中使用 SignalR 实现推送功能 罗朝辉 ( http://blog.csdn.net/kesalin ) CC许可,转载请注明出处 一,简介 Signal 是微软支持 ...

  2. MVC 中使用 SignalR 实现推送功能

    MVC 中使用 SignalR 实现推送功能 一,简介 Signal 是微软支持的一个运行在 Dot NET 平台上的 html websocket 框架.它出现的主要目的是实现服务器主动推送(Pus ...

  3. Asp.NET MVC 使用 SignalR 实现推送功能二(Hubs 在线聊天室 获取保存用户信息)

    简单介绍 关于SignalR的简单实用 请参考 Asp.NET MVC 使用 SignalR 实现推送功能一(Hubs 在线聊天室) 在上一篇中,我们只是介绍了简单的消息推送,今天我们来修改一下,实现 ...

  4. AngularJS+ASP.NET MVC+SignalR实现消息推送

    原文:AngularJS+ASP.NET MVC+SignalR实现消息推送 背景 OA管理系统中,员工提交申请单,消息实时通知到相关人员及时进行审批,审批之后将结果推送给用户. 技术选择 最开始发现 ...

  5. IOS中程序如何进行推送消息(本地推送,远程推送)

    [1]-------------什么是推送消息? 我就以一张图解释------------ [2]-----------IOS程序中如何进行本地推送?----------- 2.1,先征求用户同意 1 ...

  6. JAVA使用百度链接实时推送API提交链接

    官网地址:http://data.zz.baidu.com/ 百度推广API的token获取 http://data.zz.baidu.com/site/index 填写完之后会进行验证, 验证完之后 ...

  7. Asp.NET MVC 中使用 SignalR 实现推送功能

    一,简介Signal 是微软支持的一个运行在 Dot NET 平台上的 html websocket 框架.它出现的主要目的是实现服务器主动推送(Push)消息到客户端页面,这样客户端就不必重新发送请 ...

  8. 在 Asp.NET MVC 中使用 SignalR 实现推送功能

    一,简介Signal 是微软支持的一个运行在 Dot NET 平台上的 html websocket 框架.它出现的主要目的是实现服务器主动推送(Push)消息到客户端页面,这样客户端就不必重新发送请 ...

  9. ASP.NET MVC SignalR 简单聊天推送笔记

    介绍:(抄袭于网络) ASP.NET SignalR 是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程.实时 Web 功能是指这样一种功能:当所连接 ...

随机推荐

  1. Delphi XE6打电话

    procedure TPhoneDialerForm.btnMakeCallClick(Sender: TObject); var PhoneDialerService: IFMXPhoneDiale ...

  2. UI5-文档-4.37-Content Density

    在本演练教程的这一步中,我们将根据用户的设备调整内容密度.SAPUI5包含不同的内容密度,允许您为支持触摸的设备显示更大的控件,为鼠标操作的设备显示更小.更紧凑的设计.在我们的app中,我们将检测设备 ...

  3. vue基础——Class与Style绑定

    Class与Style绑定 操作元素的class列表和内联样式是数据绑定的一个常见的需求. 因为它们都是属性,所以我们可以用v-bind来处理它们:只需要通过表达式计算出字符串结果即可.不过,字符串拼 ...

  4. this指针的调整

    我们先来看一段代码: #include <iostream> using namespace std; class A { public: int a; A( ) { printf(&qu ...

  5. centos 安装单机版 redis4.0.10

    redis源码地址: http://download.redis.io/releases/ 下载 redis-4.0.10.tar.gz  和  redis-stable.tar.gz 第一步:安装g ...

  6. UEFI BIOS和普通BIOS的区别

    作为传统BIOS(Basic Input/Output System)的继任者,UEFI拥有前辈所不具备的诸多功能,比如图形化界面.多种多样的操作方式.允许植入硬件驱动等等.这些特性让UEFI相比于传 ...

  7. ubuntu ftp 建立匿名用户 [转]

    转自:http://www.cnblogs.com/cocoajin/p/3761414.html ubuntu server vsftpd 匿名用户上传下载及目录设置 1:vsftpd服务器安装: ...

  8. etcd 集群恢复

    七个节点,挂了5个,etcd无法访问 参考: https://coreos.com/etcd/docs/latest/op-guide/recovery.html 此次我只恢复了v3的数据 在存活的节 ...

  9. js json转对象

    使用eval() 读取 for (var i=0;i< response.length; i++) { //alert(response[i].username) html=html+" ...

  10. java script btoa与atob的

    javascript原生的api本来就支持,Base64,但是由于之前的javascript局限性,导致Base64基本中看不中用.当前html5标准正式化之际,Base64将有较大的转型空间,对于H ...