谁说长连接、长轮询必须用异步!

看了好多帖子一说长连接、长轮询、Comet之类的都是用的服务端的异步页面,大致如下:

protected void Page_Load(object sender, EventArgs e)
{
AddOnPreRenderCompleteAsync(new BeginEventHandler(BeginAsyncOperation),new EndEventHandler(EndAsyncOperation));
}

而且每个人的异步页面的用法还都不一样。搞的我这个以前没用过异步页面的程序猿一头雾水,于是就想能不能不用异步页面实现长连接。经过一番研究还是可以的,不敢独享,拿出来大家给看看,有不到之处还望指点。

这个例子是一个群聊的demo,总共就两个页面一个登陆页,一个是聊天页,先看登陆页面:

我叉,这也太简单点。恩,没办法,本人业余时间有限,主要说长连接的事。点击登陆后台代码:


1 protected void btnLogin_Click(object sender, EventArgs e)
2 {
3 string name=txtName.Text.Trim();
4 if (string.IsNullOrEmpty(name) == false)
5 {
6 Session["name"] = name;
7 Response.Redirect("Chat.aspx");
8 }
9 }

再看重点的Chat.aspx页面:

前台:


 1 <%@ Page Language="C#" AutoEventWireup="true" EnableSessionState="ReadOnly" CodeFile="Chat.aspx.cs" Inherits="Chat" %>
2
3 <!DOCTYPE html>
4
5 <html xmlns="http://www.w3.org/1999/xhtml">
6 <head>
7 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
8 <title></title>
9 <script src="jquery-1.7.1.min.js"></script>
10 <script type="text/javascript">
11 //长轮询获取信息
12 function LongPolling() {
13 $.ajax(
14 {
15 url: "Chat.aspx",
16 type: "post",
17 data: { "action": "get" },
18 success: function (data){
19 $("#content").append(data + "<br>");
20 LongPolling();
21 },
22 error: function (xhr, info, obj) {
23 $("#content").append(info + "<br>");
24 LongPolling();
25 }
26 });
27 }
28 LongPolling();
29
30 //发送消息
31 function Send() {
32 if (!$("#msg").val())
33 {
34 alert("不能发空白哦!");
35 return;
36 }
37 $.ajax(
38 {
39 url: "Chat.aspx",
40 type: "post",
41 data: { "action": "send", "msg": $("#msg").val() },
42 success: function (data)
43 {
44 //貌似什么也不用做
45 }
46 });
47 }
48 </script>
49 </head>
50 <body>
51 <div id="content" style="width:500px; height:300px; overflow-y:auto; border:1px solid red;"></div>
52 <input type="text" id="msg" />
53 <input type="button" value="发送" onclick="Send()"/>
54 </body>
55 </html>

后台代码:


  1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Threading;
5
6 /// <summary>
7 /// 注意:对应aspx页面必须加上EnableSessionState="ReadOnly"否则会造成请求阻塞
8 /// </summary>
9 public partial class Chat : BasePage
10 {
11 //全局静态变量:待发送的聊天信息
12 public static List<ChatObj> ChatObjList = new List<ChatObj>();
13 //全局静态变量:用户列表
14 public static List<string> UserList = new List<string>();
15
16 protected void Page_Load(object sender, EventArgs e)
17 {
18 //json返回的消息
19 string msg = string.Empty;
20 //验证是否登录了
21 if (Session["name"] == null)
22 {
23 Response.Redirect("Login.aspx");
25 }
26 //操作
27 string action = Request["action"];
28 //发送信息
29 if (action == "send")
30 {
31 if (string.IsNullOrEmpty(Request["msg"]) == false)
32 {
33 //模拟群聊 当前用户发的消息分发给在线的每一个人
34 foreach (var user in UserList)
35 {
36 ChatObjList.Add(new ChatObj()
37 {
38 From = Session["name"].ToString(),
39 To = user,
40 Message = Request["msg"],
41 SendTime = DateTime.Now
42 });
43 }
44 }
45 else
46 {
47 msg = "发送信息不能为空";
48 }
49 }
50 else if (action == "get")//获取信息
51 {
52 //这里是关键 检查是否有自己的消息,如果有则返回,没有则一直循环休眠
53 while (true)
54 {
55 ChatObj[] chatObjList = ChatObjList.AsEnumerable().Where(o => o.To == Session["name"].ToString()).ToArray();
56 if (chatObjList == null || chatObjList.Length == 0)
57 {
58 Thread.Sleep(1000);//休眠一秒
59 }
60 else
61 {
62 msg = string.Empty;
63 foreach (var item in chatObjList)
64 {
65 msg += item.From + "说:" + item.Message+"<br>";
66 ChatObjList.Remove(item);
67 }
68 break;
69 }
70 }
71 }
72 Response.Write(msg);
73
74 if (string.IsNullOrEmpty(action) == false)
75 {
76 //如果是ajax请求则终止响应,否则会输出整个页面的html
77 Response.End();
78 }
79 else
80 {
81 //首次加载则把用户加入到用户列表 不太完善主要演示longpolling
82 if (UserList.Contains(Session["name"].ToString())==false)
83 {
84 UserList.Add(Session["name"].ToString());
85 }
86 }
87 }
88 }
89
90 /// <summary>
91 /// 发送消息对象
92 /// </summary>
93 public class ChatObj
94 {
95 /// <summary>
96 /// 发送方
97 /// </summary>
98 public string From { get; set; }
99 /// <summary>
100 /// 接收方
101 /// </summary>
102 public string To { get; set; }
103 /// <summary>
104 /// 消息
105 /// </summary>
106 public string Message { get; set; }
107 /// <summary>
108 /// 发送时间
109 /// </summary>
110 public DateTime SendTime { get; set; }
111 }

代码里注释已经很清楚了,确实也没用到异步页面。不过有一个要注意的地方就是Session的读写锁,以前没关注这个,必须用EnableSessionState="ReadOnly"把读锁之间、分开,否则会造成请求阻塞,用两个页面是为了把登陆时的写锁和获取信息时的读锁分开,在这个问题上花了不少功夫。Session读写锁请参考:http://www.cnblogs.com/OpenCoder/archive/2010/01/10/1643659.html

微软有个signalR的东西专门做消息推送、及时消息这块的,有兴趣的同学可以看看,已经第二版了。

下一个博客会写某驾校约车插件,用chrome插件开发。拜拜

时间: 2024-09-27 20:00:43

谁说长连接、长轮询必须用异步!的相关文章

php客服聊天回话系统,长连接加ajax轮询实现

客服回话系统有三种实现方法: 1.用ajax每隔几秒钟请求一次服务器,看看有没得消息,有消失就返回来显示给用户. 2.长连接:建立一次连接之后就不断开,php set_time_out(0) 用ob_flush flush等函数强制推送给客户端 3.长连接加轮询,建立一个长连接,没有数据就一直连着,当有数据的时候,就返回数据,并结束当前的连接,客户端接受数据并显示,然后再连接服务器端,又开始长连接,就这样周而复始,这就是长轮询. 今天,我们就用第三种方法来实现php客服聊天系统. 只写我的思路:

Apollo 3 定时/长轮询拉取配置的设计

前言 如上图所示,Apollo portal 更新配置后,进行轮询的客户端获取更新通知,然后再调用接口获取最新配置.不仅仅只有轮询,还有定时更新(默认 5 分钟一次).目的就是让客户端能够稳定的获取到最新的配置. 一起来看看他的设计. 核心代码 具体的类是 RemoteConfigRepository,每一个 Config -- 也就是 namespace 都有一个 RemoteConfigRepository 对象,表示这个 Config 的远程配置仓库,可以利用这个仓库请求远程服务,得到配置

基于分布式Http长连接框架--架构模型

我画了个简单的架构图来帮助说明: 其实为发布订阅架构模式. 生产者和消费者我们统一可理解为客户端,消息中间件可认为是服务端. 生产者和消费者做为客户端要跟服务端交互,则先通过代理订阅服务端,订阅成功后即可跟服务端互通互联,此刻的连接通道为长连接. 长连接的优势在于会将消息主动通知到客户端,避免客户端去做大量的轮询工作而造成资源浪费,而且对于移动应用来说,可较大程度上节省GPRS流量. 当连接建立好后,生产者可随时发送消息,如果在发消息过程当中,服务端由于各种原因不能连接,则消息的发送会回放重试,

TCP/IP系列——长连接与短连接的区别

1 什么是长连接和短连接 三次握手和四次挥手 TCP区别于UDP最重要的特点是TCP必须建立在可靠的连接之上,连接的建立和释放就是握手和挥手的过程. 三次握手为连接的建立过程,握手失败则连接建立失败. 四次挥手为连接的完整释放过程,也会发生某个消息丢失或者超时的情况,有一方主动发送FIN消息即表示连接即将释放. 注:SYN.ACK.FIN消息具有哪些含义,以及连接的状态,请参考<TCP/IP详解 卷1>第18章. 长连接 长连接,也叫持久连接,在TCP层握手成功后,不立即断开连接,并在此连接的

HTTP长连接和短连接及应用情景

HTTP短连接 HTTP/1.0中默认使用短连接, 客户端和服务器进行一次HTTP操作, 就需要建立一次连接, 任务结束连接也关闭. 当客户端浏览器访问的web网页中包含其他的web资源时, 每遇到一个web资源都会再重新建立一次连接. 一般情况下, web网站的http服务都采用短连接, 因为长连接会耗费服务器的资源, 当用户量很大且采用长连接时, 并发量很大, 每个用户无需频繁操作时采用短连接就可以. HTTP长连接 从HTTP/1.1起, 默认使用长连接, 用来保持连接性. 使用长连接的H

Web 通信 之 长连接、长轮询(long polling)(转载)

基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强了程序的实时性和交互性. 一.什么是长连接.长轮询? 用通俗易懂的话来说,就是客户端不停的向服务器发送请求以获取最新的数据信息.这里的“不停”其实是有停止的,只是我们人眼无法分辨是否停止,它只是一种快速的停下然后又立即开始连接而已. 二.长连接.长轮询的应用场景 长连接.长轮询一般应用与WebIM.ChatRoom和一些需要及时交互的网站应用中.其真实案例有:WebQQ

HTTP协议中的短轮询、长轮询、长连接和短连接

HTTP协议中的短轮询.长轮询.长连接和短连接 引言 最近刚到公司不到一个月,正处于熟悉项目和源码的阶段,因此最近经常会看一些源码.在研究一个项目的时候,源码里面用到了HTTP的长轮询.由于之前没太接触过,因此LZ便趁着这个机会,好好了解了一下HTTP的长长短短. 了解的方式主要都是LZ在网络上获取的,这里只是谈一下LZ对于这四种叫法最直观的理解.如果你之前不懂的话,可以帮你普及一下,如果你之前就懂得话,可以互相对照一下. 以前的误解 很久之前LZ就听说过长连接的说法,而且还知道HTTP1.0协

Web 通信 之 长连接、长轮询(long polling)

基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强了程序的实时性和交互性. 一.什么是长连接.长轮询? 用通俗易懂的话来说,就是客户端不停的向服务器发送请求以获取最新的数据信息.这里的“不停”其实是有停止的,只是我们人眼无法分辨是否停止,它只是一种快速的停下然后又立即开始连接而已. 二.长连接.长轮询的应用场景 长连接.长轮询一般应用与WebIM.ChatRoom和一些需要及时交互的网站应用中.其真实案例有:WebQQ

误人子弟的网络,谈谈HTTP协议中的短轮询、长轮询、长连接和短连接

引言 最近刚到公司不到一个月,正处于熟悉项目和源码的阶段,因此最近经常会看一些源码.在研究一个项目的时候,源码里面用到了HTTP的长轮询.由于之前没太接触过,因此LZ便趁着这个机会,好好了解了一下HTTP的长长短短. 了解的方式主要都是LZ在网络上获取的,这里只是谈一下LZ对于这四种叫法最直观的理解.如果你之前不懂的话,可以帮你普及一下,如果你之前就懂得话,可以互相对照一下. 以前的误解 很久之前LZ就听说过长连接的说法,而且还知道HTTP1.0协议不支持长连接,从HTTP1.1协议以后,连接默