基于 C# Ashx 与长轮询实现简易在线聊天室
在 HTML5 WebSocket 普及之前,实现网页版即时通讯通常依赖定时轮询或长连接+长轮询技术。本文提供一个基于 C# (ASP.NET) 和原生 JavaScript/AJAX 的多人聊天室实现方案,利用长轮询维持实时性,并通过内存集合管理用户状态与聊天记录。
实现原理与架构
该聊天室采用前后端分离的简单结构,不依赖第三方库或数据库:
- 前端交互:使用原生 JavaScript 发送 AJAX 请求,接收 JSON 格式数据并动态渲染聊天记录与在线列表。
- 后端处理:C#
.ashx一般处理程序作为核心服务,负责解析客户端请求(发送消息、获取消息、设置状态)。 - 通信模式:采用长轮询机制。前端持续请求后端获取未读消息,后端在有新消息时立即响应,从而实现近实时的信息推送。
- 数据存储:所有聊天记录和在线用户列表均保存在服务器端的静态内存集合中。
服务端核心逻辑 (C#)
服务端代码位于 ChatHandler.ashx 中,继承自 IHttpHandler。主要涉及线程安全的并发操作,因为多个用户可能同时访问。
第1步:定义数据结构与存储容器
服务端需维护两个主要的静态集合:一个用于存储聊天消息,一个用于记录当前在线用户名。由于是多线程环境,必须引入锁机制(如 lock 或 ReaderWriterLockSlim)来保证数据读写的安全性。
// 消息实体类定义
private class Msg {
public string name { get; set; }
public string sendtime { get; set; }
public string content { get; set; }
// ... 其他属性如 readedCount 等
}
// 全局静态变量
private static List<Msg> msgs = new List<Msg>();
private static List<string> onLineNames = new List<string>;
private static object syncObject = new object();
第2步:实现消息发送与状态同步
当用户点击“发送”或“进入聊天室”时,前端调用 ProcessRequest 中的对应 Case。后端会将新消息封装成对象加入 msgs 列表,并将当前时间戳和内容存入。
case "send":
{
responseObject = SendMessage(chatName, msg, "normal");
break;
}
case "on":
{
// 将用户名加入在线列表
lock (syncObject)
{
onLineNames.Add(chatName);
}
// 生成一条特殊的上线通知消息
responseObject = SetChatStatus(chatName, actionName);
break;
}
注意:为了简化演示,使用了 lock(syncObject) 进行简单的互斥锁保护。在生产环境中,建议根据实际负载选择更精细的锁策略或使用分布式缓存。
第3步:实现长轮询获取新消息
这是实现即时性的关键。前端不断发起 action=receive 请求,后端需要检查是否有该用户未读取的消息。如果有,立即返回;如果没有,则让线程短暂休眠(如 Thread.Sleep(1000)),然后循环检查,直到有新消息到达才退出循环并返回结果。这种循环等待机制构成了“长轮询”。
前端交互实现 (JavaScript + AJAX)
前端页面是一个纯 HTML 文件,通过内嵌 JS 完成所有逻辑。核心功能包括初始化 DOM、绑定按钮事件以及周期性轮询。
第4步:构建 AJAX 通信层
创建一个通用的 callAjax 函数,封装 XMLHttpRequest 对象。设定请求方式为 POST,目标为 ChatHandler.ashx,并将参数序列化为查询字符串发送。
function callAjax(ajax, param, callback) {
ajax.open("post", "ChatHandler.ashx", true);
ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
ajax.onreadystatechange = function () {
if (ajax.readyState == 4 && ajax.status == 200) {
var json = eval("(" + ajax.responseText + ")");
callback(json);
}
};
ajax.send(param);
}
第5步:实现消息展示与自动更新
收到后端返回的 JSON 后,解析其中的消息数组,并在聊天框内插入新的 DOM 节点。对于用户的上下线状态变化,还需刷新右侧的在线人员列表。
图例:张三视角下的聊天界面,显示双方对话与顶部栏信息。
运行效果测试
启动 IIS 或 VS 内置服务器后,打开多个浏览器标签页模拟不同用户。在各自昵称输入框中输入名称并点击“确认进入”,即可看到彼此在线。
图例:李四视角,此时可以看到张三已上线的提示信息。
在任一窗口发送消息,其他窗口会在几秒钟内(取决于轮询间隔)自动刷出最新内容。当某用户关闭页面或断开连接时,window.onunload 事件会触发最后一次的离线通知请求,确保其他用户看到离线的提示。
图例:小美视角,展示多人同时在线及历史记录滚动加载的效果。
总结与注意事项
该方案虽然简陋,但清晰地展示了在没有现代 Web Socket 技术支持下,如何利用传统 HTTP 协议栈构建即时互动应用。关键点在于理解:
- 后端如何通过循环阻塞来实现类似推流的伪实时响应。
- 前端如何维护本地会话状态并与服务器保持心跳般的请求频率。
如果在实际部署中遇到消息延迟或内存溢出问题,可考虑将静态集合替换为 Redis 或 Memcached,并优化轮询的频率与锁的粒度。
以上就是基于 C# Ashx 与长轮询实现简易在线聊天室的详细内容,更多关于 C# 网络编程及前端异步通信的资料请关注本站其它相关文章!本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













