65.9K
CodeProject 正在变化。 阅读更多。
Home

内存中的 P2P 聊天

2014年7月13日

CPOL

3分钟阅读

viewsIcon

19707

downloadIcon

467

本文描述了一个低资源消耗的 P2P 聊天系统的设计。

引言

如果有一个可以提供 100% 隐私的聊天门户怎么样? 是的,实际上这是不可能的,但至少我们能不能设法不在服务器中存储用户的个人聊天消息?

本文试图设计这样一个聊天系统。 我使用了所有想到的语言功能,所以请记住,还有更好和其他合适的选择。

解决方案设计

需求:一个非常简单的聊天程序,允许个人相互聊天,同时不将他们的个人消息保存在数据库中。

解决方案:将消息临时保存在内存对象中,直到它传递给其他用户或直到特定的时间延迟到期,例如 2 分钟。

技术详情

这里,使用静态 List<> 来临时存储消息。 浏览器将以定义的间隔(例如:3 秒)异步地从该对象中提取消息并在浏览器中显示。 一旦消息从对象中读取,这些消息将立即被删除。 列表中孤立的消息也会以定义的间隔删除,以便变量内存消耗保持在最低水平。

示例应用程序中使用的技术和特性有

  1. HTML5 和 CSS
  2. jQuery - 版本:1.10.2
  3. 基于 .NET Framework 4.5 的带有 C# 的 ASP.NET

在此示例中,没有使用任何复杂的像 WebAPI 这样的技术,因此该功能可以很容易地以任何语言实现。

P2P 聊天涉及两个人之间的聊天。 让我把他们称为和一个陌生人

使用代码

客户端代码

以下是用 jQuery 编写的 PUSH 和 PULL 聊天消息处理程序。

$(function () {
        $("#t").focus();
        $("#s").click(function () { // PUSH
            if ($("#t").val().trim() != "") {
                u1 = $("#u1").val();
                u2 = $("#u2").val();
                $.ajax({
                    url: "e.aspx",
                    type: "POST",
                    data: { c: "p", u1: u1, u2: u2, t: escape($("#t").val()) }
                }); 
        // Pushes new message along with user1 (you) and user2 (stranger)'s usernames
            }
            $("#t").val("").focus();
        });
        
        
    });
    function pull() { // PULL - check server to see if any new messages available
        u1 = $("#u1").val();
        u2 = $("#u2").val();
        if (u1.trim() == "" || u2.trim() == "") return;
        $.ajax({
            url: "e.aspx",
            type: "POST",
            data: { c: "g", u1: u1, u2:u2 }
        })
        .done(function (d) {
            $.each($.parseJSON(d), function (k, v) {
                var cls = "cu";
                var me = v.wu;
                if (v.wu == u1) {
                    cls = "cu1";
                }
                
                $("#c").html($("#c").html() + " <span class='" + cls + "'>" + me + ": " + v.msg + "</span><br />");
                $("#c").scrollTop(1000000);
            });
        });
    }

并且,pull() 每 X 秒执行一次,例如

setInterval(pull, 1000);

服务器端代码

以下代码显示了如何处理从浏览器触发的 PULL 和 PUSH 命令。

首先,聊天消息记录看起来像这样

public class REC
{
    public string user1 { get; set; } // your nick
    public string user2 { get; set; } // stranger's nick
    public string msg { get; set; } // chat message
    public string wu { get; set; } // prointer to which user's message
    public DateTime dt { get; set; } // datetime details of message for the use of removing orphen messages
}

以下是我们内存存储对象的声明

public static List<REC> data;

接下来是 PUSH 和 PULL 处理程序。

string ret = null;
u1 = Request["u1"].ToString().ToLower();
u2 = Request["u2"].ToString().ToLower();
switch (Request["c"])
{
    case "p": // PUSH
        var t = Uri.UnescapeDataString(Request["t"].ToString());
        DateTime dt = DateTime.UtcNow;
        data.Add(new REC(u1, u2, t, u1, dt));
        data.Add(new REC(u2, u1, t, u1, dt));
        ret = "1";
        break;
    case "g": // PULL
        var z = data.Where(x => (x.user1.Contains(u1)));
        ret = new JavaScriptSerializer().Serialize(z);
        data.RemoveAll(x => (x.user1.Contains(u1)));
        data.RemoveAll(x => (DateTime.UtcNow - x.dt).TotalMinutes > 2); // remove orphen messages after 2 mins
        break;
}
Response.Write(ret);

PUSH:将传入的聊天消息添加到数据中。 您可以看到,插入了两条记录 - 一条针对,另一条针对陌生人

PULL:检索特定用户的聊天消息。 检索后,立即将其从数据对象中删除。 第二个 RemoveAll() lamda 删除任何性质为孤立的消息。 由于网络问题或浏览器关闭,可能存在未交付的未使用消息。

注意事项

  1. 静态 List<> 是我首先想到的,但请注意,不建议使用静态方法。 如果应用程序域被回收,它可能会丢失值,它不适用于负载均衡的环境,它的存储能力取决于你的机器拥有多少内存等等。 请探索其他内存存储方式
  2. 除非进行修改以提高可扩展性,否则此示例应用程序不可扩展
  3. 此设计不考虑群聊。
  4. 如果第三个人使用第一个或第二个用户的昵称之一,系统将表现得很奇怪
  5. 示例代码中没有适当的异常处理
  6. 编码最佳实践几乎没有遵循

演示

在此处托管了一个示例演示。 但我不知道它将可用多久,所以如果链接不起作用,请不要抱怨。

© . All rights reserved.