Backend Development
C#.Net Tutorial
Asp.net uses SignalR to implement cool end-to-end chat function1. Introduction
In the previous article, SignalR has been introduced in detail, and its application in Asp.net MVC and WPF has been briefly introduced. The last blog post introduced the implementation of group messaging. However, SignalR was born for real-time chat, so it naturally lacks the end-to-end chat unlike QQ. This blog post will introduce how to use SignalR to implement functions similar to QQ chat.
2. The idea of using SignalR to implement end-to-end chat
Before introducing the specific implementation, I first introduced the idea of using SignalR to implement end-to-end chat. I believe you have seen code like Clients.All.sendMessage(name, message); in the previous article, which means calling SendMessage of all clients. SignalR's hub enables real-time communication between clients and servers. To achieve end-to-end chat, naturally you cannot send messages to all clients, but can only send messages to specific clients. Otherwise, it will be chaotic and there will be no privacy. So how can I send a message to a specific client? This problem is the key to our implementation of end-to-end chat function.
In addition to the All attribute, the Clients object we send also has other attributes. You can press F12 in VS to view all attributes or methods of the Clients object. The specific definition is as follows:
public interface IHubConnectionContext<T>
{
T All { get; } // 代表所有客户端
T AllExcept(params string[] excludeConnectionIds); // 除了参数中的所有客户端
T Client(string connectionId); // 特定的客户端,这个方法也就是我们实现端对端聊天的关键
T Clients(IList<string> connectionIds); // 参数中的客户端端
T Group(string groupName, params string[] excludeConnectionIds); // 指定客户端组,这个也是实现群聊的关键所在
T Groups(IList<string> groupNames, params string[] excludeConnectionIds);
T User(string userId); // 特定的用户
T Users(IList<string> userIds); // 参数中的用户
}
In SignalR, every To mark a client's uniqueness, SignalR will assign it a ConnectionId, so that we can find the specific client through the ConnectionId. In this way, when we send a message to a client, in addition to passing in the message, we also need to enter the ConnectionId sent to the other party, so that the server can forward the corresponding message to the corresponding client based on the incoming ConnectionId. Served. This completes the end-to-end chat function. In addition, if the user is not online, the server can save the message to the database. When the corresponding client comes online, it can check from the database whether the client has any messages that need to be pushed. If so, retrieve the data from the database. , push the data to the client. (However, the function of caching data on the server side is not implemented in this blog post. The introduction here is to let everyone understand one of the implementation principles of QQ).
Let’s sort out the implementation ideas of the end-to-end chat function:
When the client logs in, it records the client’s ConnectionId and adds the user to a static array. This data is used to record all online users.
Users can click on the user chat among online users. When sending a message, the ConnectionId needs to be passed to the server.
The server calls the Clients.Client(connnection).sendMessage method based on the incoming message content and ConnectionId to forward it to the corresponding client.
3. Implement the core code of cool chat function
With the implementation idea, it is easy to implement the function. Next, let us first take a look at the code in the hub ChatHub:
public class ChatHub : Hub
{
// 静态属性
public static List<UserInfo> OnlineUsers = new List<UserInfo>(); // 在线用户列表
/// <summary>
/// 登录连线
/// </summary>
/// <param name="userId">用户Id</param>
/// <param name="userName">用户名</param>
public void Connect(string userId, string userName)
{
var connnectId = Context.ConnectionId;
if (OnlineUsers.Count(x => x.ConnectionId == connnectId) == 0)
{
if (OnlineUsers.Any(x => x.UserId == userId))
{
var items = OnlineUsers.Where(x => x.UserId == userId).ToList();
foreach (var item in items)
{
Clients.AllExcept(connnectId).onUserDisconnected(item.ConnectionId, item.UserName);
}
OnlineUsers.RemoveAll(x => x.UserId == userId);
}
//添加在线人员
OnlineUsers.Add(new UserInfo
{
ConnectionId = connnectId,
UserId = userId,
UserName = userName,
LastLoginTime = DateTime.Now
});
}
// 所有客户端同步在线用户
Clients.All.onConnected(connnectId, userName, OnlineUsers);
}
/// <summary>
/// 发送私聊
/// </summary>
/// <param name="toUserId">接收方用户连接ID</param>
/// <param name="message">内容</param>
public void SendPrivateMessage(string toUserId, string message)
{
var fromUserId = Context.ConnectionId;
var toUser = OnlineUsers.FirstOrDefault(x => x.ConnectionId == toUserId);
var fromUser = OnlineUsers.FirstOrDefault(x => x.ConnectionId == fromUserId);
if (toUser != null && fromUser != null)
{
// send to
Clients.Client(toUserId).receivePrivateMessage(fromUserId, fromUser.UserName, message);
// send to caller user
// Clients.Caller.sendPrivateMessage(toUserId, fromUser.UserName, message);
}
else
{
//表示对方不在线
Clients.Caller.absentSubscriber();
}
}
/// <summary>
/// 断线时调用
/// </summary>
/// <param name="stopCalled"></param>
/// <returns></returns>
public override Task OnDisconnected(bool stopCalled)
{
var user = OnlineUsers.FirstOrDefault(u => u.ConnectionId == Context.ConnectionId);
// 判断用户是否存在,存在则删除
if (user == null) return base.OnDisconnected(stopCalled);
Clients.All.onUserDisconnected(user.ConnectionId, user.UserName); //调用客户端用户离线通知
// 删除用户
OnlineUsers.Remove(user);
return base.OnDisconnected(stopCalled);
}
}
The above is The main implementation of the server, let’s take a look at the client’s implementation code:
<script type="text/javascript">
var systemHub = $.connection.chatHub;
/ 连接IM服务器成功
// 主要是更新在线用户
systemHub.client.onConnected = function (id, userName, allUsers) {
var node = chatCore.node, myf = node.list.eq(0), str = '', i = 0;
myf.addClass('loading');
onlinenum = allUsers.length;
if (onlinenum > 0) {
str += '<li class="ChatCore_parentnode ChatCore_liston">'
+ '<h5 id="i-i-span-nbsp-class-ChatCore-parentname-在线用户-span-em-nbsp-class-ChatCore-nums-nbsp-nbsp-onlinenum-nbsp-nbsp-em"><i></i><span class="ChatCore_parentname">在线用户</span><em class="ChatCore_nums">(' + onlinenum + ')</em></h5>'
+ '<ul id="ChatCore_friend_list" class="ChatCore_chatlist">';
for (; i < onlinenum; i++) {
str += '<li id="userid-' + allUsers[i].UserID + '" data-id="' + allUsers[i].ConnectionId + '" class="ChatCore_childnode" type="one"><img class="ChatCore_oneface lazy" src="/static/imghwm/default1.png" data-src="/Content/Images/001.jpg?' + allUsers[i].UserID + '" alt="Asp.net uses SignalR to implement cool end-to-end chat function" ><span class="ChatCore_onename">' + allUsers[i].UserName + '(' + ')</span><em class="ChatCore_time">' + allUsers[i].LoginTime + '</em></li>';
}
str += '</ul></li>';
myf.html(str);
} else {
myf.html('<li class="ChatCore_errormsg">没有任何数据</li>');
}
myf.removeClass('loading');
};
//消息传输
chatCore.transmit = function () {
var node = chatCore.node, log = {};
node.sendbtn = $('#ChatCore_sendbtn');
node.imwrite = $('#ChatCore_write');
//发送
log.send = function () {
var data = {
content: node.imwrite.val(),
id: chatCore.nowchat.id,
sign_key: '', //密匙
_: +new Date
};
if (data.content.replace(/\s/g, '') === '') {
layer.tips('说点啥呗!', '#ChatCore_write', 2);
node.imwrite.focus();
} else {
//此处皆为模拟
var keys = chatCore.nowchat.type + chatCore.nowchat.id;
//聊天模版
log.html = function (param, type) {
return '<li class="' + (type === 'me' ? 'ChatCore_chateme' : '') + '">'
+ '<div class="ChatCore_chatuser">'
+ function () {
if (type === 'me') {
return '<span class="ChatCore_chattime">' + param.time + '</span>'
+ '<span class="ChatCore_chatname">' + param.name + '</span>'
+ '<img src="/static/imghwm/default1.png" data-src="' + param.face + '" class="lazy" alt="Asp.net uses SignalR to implement cool end-to-end chat function" >';
} else {
return '<img src="/static/imghwm/default1.png" data-src="' + param.face + '" class="lazy" alt="Asp.net uses SignalR to implement cool end-to-end chat function" >'
+ '<span class="ChatCore_chatname">' + param.name + '</span>'
+ '<span class="ChatCore_chattime">' + param.time + '</span>';
}
}()
+ '</div>'
+ '<div class="ChatCore_chatsay">' + param.content + '<em class="ChatCore_zero"></em></div>'
+ '</li>';
};
log.imarea = chatCore.chatbox.find('#ChatCore_area' + keys);
log.imarea.append(log.html({
time: new Date().toLocaleString(),
name: config.user.name,
face: config.user.face,
content: data.content
}, 'me'));
node.imwrite.val('').focus();
log.imarea.scrollTop(log.imarea[0].scrollHeight);
// 调用服务端sendPrivateMessage方法来转发消息
systemHub.server.sendPrivateMessage(chatCore.nowchat.id, data.content);
}
};
node.sendbtn.on('click', log.send);
node.imwrite.keyup(function (e) {
if (e.keyCode === 13) {
log.send();
}
});
};
//用户离线
systemHub.client.onUserDisconnected = function (id, userName) {
onlinenum = onlinenum - 1;
$(".ChatCore_nums").html("(" + onlinenum + ")");
$("#ChatCore_friend_list li[data-id=" + id + "]").remove();
};
// 启动连接
$.connection.hub.start().done(function () {
systemHub.server.connect(userid, username); // 调用服务端connect方法
});
</script>
The above only lists some core code implementations. In addition, in order to achieve cool effects, a Jquery plug-in is used here: layer, the official website is: http://layer.layui.com/. This plug-in is mainly used to achieve the effects of pop-up boxes and pop-up layers. To achieve cool chat effects, you need to write JS code yourself. Since I am not very familiar with the front-end, this JS special effects code is also based on the implementation on the Internet. If you want to run it and see the effect, it is recommended to download the source code at the end of the article and run it.
4. Final effect
After introducing the implementation ideas and implementation code, now that we have reached our exciting moment, that is to see if our implemented functions can meet the needs. In addition, in addition to meeting the basic chat functions, You also need to see if the interface is cool enough.

For more related articles about Asp.net using SignalR to implement cool end-to-end chat functions, please pay attention to the PHP Chinese website!
From Web to Desktop: The Versatility of C# .NETApr 15, 2025 am 12:07 AMC#.NETisversatileforbothwebanddesktopdevelopment.1)Forweb,useASP.NETfordynamicapplications.2)Fordesktop,employWindowsFormsorWPFforrichinterfaces.3)UseXamarinforcross-platformdevelopment,enablingcodesharingacrossWindows,macOS,Linux,andmobiledevices.
C# .NET and the Future: Adapting to New TechnologiesApr 14, 2025 am 12:06 AMC# and .NET adapt to the needs of emerging technologies through continuous updates and optimizations. 1) C# 9.0 and .NET5 introduce record type and performance optimization. 2) .NETCore enhances cloud native and containerized support. 3) ASP.NETCore integrates with modern web technologies. 4) ML.NET supports machine learning and artificial intelligence. 5) Asynchronous programming and best practices improve performance.
Is C# .NET Right for You? Evaluating its ApplicabilityApr 13, 2025 am 12:03 AMC#.NETissuitableforenterprise-levelapplicationswithintheMicrosoftecosystemduetoitsstrongtyping,richlibraries,androbustperformance.However,itmaynotbeidealforcross-platformdevelopmentorwhenrawspeediscritical,wherelanguageslikeRustorGomightbepreferable.
C# Code within .NET: Exploring the Programming ProcessApr 12, 2025 am 12:02 AMThe programming process of C# in .NET includes the following steps: 1) writing C# code, 2) compiling into an intermediate language (IL), and 3) executing by the .NET runtime (CLR). The advantages of C# in .NET are its modern syntax, powerful type system and tight integration with the .NET framework, suitable for various development scenarios from desktop applications to web services.
C# .NET: Exploring Core Concepts and Programming FundamentalsApr 10, 2025 am 09:32 AMC# is a modern, object-oriented programming language developed by Microsoft and as part of the .NET framework. 1.C# supports object-oriented programming (OOP), including encapsulation, inheritance and polymorphism. 2. Asynchronous programming in C# is implemented through async and await keywords to improve application responsiveness. 3. Use LINQ to process data collections concisely. 4. Common errors include null reference exceptions and index out-of-range exceptions. Debugging skills include using a debugger and exception handling. 5. Performance optimization includes using StringBuilder and avoiding unnecessary packing and unboxing.
Testing C# .NET Applications: Unit, Integration, and End-to-End TestingApr 09, 2025 am 12:04 AMTesting strategies for C#.NET applications include unit testing, integration testing, and end-to-end testing. 1. Unit testing ensures that the minimum unit of the code works independently, using the MSTest, NUnit or xUnit framework. 2. Integrated tests verify the functions of multiple units combined, commonly used simulated data and external services. 3. End-to-end testing simulates the user's complete operation process, and Selenium is usually used for automated testing.
Advanced C# .NET Tutorial: Ace Your Next Senior Developer InterviewApr 08, 2025 am 12:06 AMInterview with C# senior developer requires mastering core knowledge such as asynchronous programming, LINQ, and internal working principles of .NET frameworks. 1. Asynchronous programming simplifies operations through async and await to improve application responsiveness. 2.LINQ operates data in SQL style and pay attention to performance. 3. The CLR of the NET framework manages memory, and garbage collection needs to be used with caution.
C# .NET Interview Questions & Answers: Level Up Your ExpertiseApr 07, 2025 am 12:01 AMC#.NET interview questions and answers include basic knowledge, core concepts, and advanced usage. 1) Basic knowledge: C# is an object-oriented language developed by Microsoft and is mainly used in the .NET framework. 2) Core concepts: Delegation and events allow dynamic binding methods, and LINQ provides powerful query functions. 3) Advanced usage: Asynchronous programming improves responsiveness, and expression trees are used for dynamic code construction.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

PhpStorm Mac version
The latest (2018.2.1) professional PHP integrated development tool

WebStorm Mac version
Useful JavaScript development tools

Atom editor mac version download
The most popular open source editor

Dreamweaver Mac version
Visual web development tools






