SignalR聊天室,在将其保存到Sql数据库后收到消息的确认

时间:2015-05-05 06:58:19

标签: c# asp.net signalr

大家好我不知道我是什么信号我在聊天模块中按照正确的方法提供一些帮助 我的推荐: http://www.codeproject.com/Articles/562023/Asp-Net-SignalR-Chat-Room但本文不使用dataBase 我用来构建聊天模块的步骤是:
1 - 从chatHub类继承的创建的Hub类 2 - 在Connect(string enryptedId)班级的chatHub功能中,我将添加到List<UserDetail>
3 - 在SendPrivateMessage(string toData)如果它成功保存到dataBase而没有任何异常,则将其保存到数据库,然后将其发送给发送方和接收方并绑定其通信消息<div>

此方法中的问题 - 如果由于网络问题导致发件人断开连接后将其保存到数据库,则发件人将不会收到来自chathub类到客户端功能的消息,因此消息不会附加到显示用户通信的<div>但实际上消息发送成功。
请任何人告诉我正确的做法。

3 个答案:

答案 0 :(得分:0)

发送消息时,在消息的开头附加一个包含8个字符的随机字符串。在您的消息接收功能上,删除前8个字符并将其发送回原始发件人。

如果您从接收方收到相同的字符,那么您知道接收方已收到该消息且尚未断开连接。

您可以使用此方法生成随机字符串。

private static IEnumerable<string> RandomStrings(
    string allowedChars,
    int minLength,
    int maxLength,
    Random rng)
{
    char[] chars = new char[maxLength];
    int setLength = allowedChars.Length;

    int length = rng.Next(minLength, maxLength + 1);

        for (int i = 0; i < length; ++i)
        {
            chars[i] = allowedChars[rng.Next(setLength)];
        }

        return new string(chars, 0, length);
}

你可以这样调用这个方法

private string GetRandomStrings(){
    const string AllowedChars =
        "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#@$^*()";
    Random rng = new Random();
    return RandomStrings(AllowedChars, 8, 8, 1, rng)
}

答案 1 :(得分:0)

我会这样做,记住它没有经过测试的Pseduo代码或任何东西

private Dictionary<Guid, TaskCompletionSource<bool>> transactions = new Dictionary<Guid, TaskCompletionSource<bool>>();

public Task SendPrivateMessage(string content)
{
    var taskCompletion = new TaskCompletionSource<bool>();
    var transactionId = Guid.NewGuid();

    transactions[transactionId] = taskCompletion;
    var message = new Message
    {
        TransactionId = transactionId,
        Content = content
    };

    GlobalHost
        .ConnectionManager
        .GetHubContext<MyHub>()
        .Clients
        .Client(connectionId)
        .OnMessage(message); 

    return taskCompletion.Task;
}

public void OnTransactionConfirmed(Guid transactionId)
{
    var taskCompletion = transactions[transactionId];
    transactions.Remove(transactionId);
    taskCompletion.SetResult(true);
}

消息只是一个DTO

public class Message
{
    public Guid TransactionId { get; set; }
    public string Content { get; set; }
}

基本上,您使用名为OnMessage的客户端方法向客户端发送消息,然后异步等待,直到客户端使用名为OnTransactionConfirmed方法确认

使用任务可以更容易地以同步方式异步工作,SendPrivateMessage的使用者本身可以是异步的(如果从WebApi方法或类似方法调用它)。

public Task MyWebApiMethod() 
{
   return myChatLogic.SendPrivateMessage("foo");
}

或以同步方式

public void MySyncMethod() 
{
   myChatLogic.SendPrivateMessage("foo").Wait(); //Thread will wait here until client asnwers
}

注意 要使此代码失效,您需要超时等待确认并完成任务并删除transactionId等

答案 2 :(得分:0)

您的发送消息,接收消息和显示消息应单独处理。您使用发送消息做得很好,除了您需要添加服务器生成的日期时间戳(不要使用客户端的时间)到每条消息并将其存储在sql中。无论何时收到新消息,服务器都应将此消息发送给所有在线发件人和接收者的客户端浏览器或应用程序。

这里我说发送者因为用户A可以使用手机登录并同时使用办公桌面浏览器登录,如果用户A使用桌面浏览器向用户B手机发送消息,此消息应该出现在3个客户端设备:用户桌面浏览器,用户A手机和用户B手机。

对于接收者,无论何时从离线到在线,使用cookie或文件或客户端sqlite或客户端内部存储,使用Server数据库检查客户端存储的最后一条消息日期时间,并通过比较上次离线获取所有相关消息来自客户端的最后一条消息日期时间和来自服务器数据库的消息dt。

显示消息,仅从客户端存储读取,以便应用程序可以脱机运行。