.NET Core和SignalR实现一个简单版聊天系统——客户端1

前两篇写完了服务端的一些代码,接下来写winform客户端的。

SignalR聊天系统的服务端以及数据库1https://blog.csdn.net/hyx1229/article/details/121258116?spm=1001.2014.3001.5501icon-default.png?t=LA92https://blog.csdn.net/hyx1229/article/details/121258116?spm=1001.2014.3001.5501SignalR聊天系统服务端的方法 2https://blog.csdn.net/hyx1229/article/details/121277634?spm=1001.2014.3001.5501icon-default.png?t=LA92https://blog.csdn.net/hyx1229/article/details/121277634?spm=1001.2014.3001.5501

一、与服务端连接的静态类

在winform的根目录下建一个类,ChatService.cs,建静态类是为了让三个窗体能共用这些方法和数据,需要先在nuget中安装Microsoft.AspNetCore.SignalR.Client这个包

然后我将解释以下代码

静态的UserId:存放自己账户的id,后续获取自己的好友列表,添加好友等都需要用到 

UserList:用于存放自己的好友列表

Connection:就是SignalR连接的上下文了,后续通过它来调用服务端的方法

1.1 await Connection.StartAsync()方法

开启连接,连接成功后服务端可以里面输出当前连接的连接id,只需在服务端中重写Hub的OnConnectedAsync方法 ,服务端全部代码

/// <summary>
        /// 新连接
        /// </summary>
        /// <returns></returns>
        public override async Task OnConnectedAsync()
        {
            Console.WriteLine($"新连接{Context.ConnectionId}");
            await base.OnConnectedAsync();
        }

这里只要我先打开服务端,再启动winform就能看到这个效果,注意你每次重新启动winform,这个连接id是不一样的。所以我们会在用户登录后把它的连接id存到内存中而不是放到数据库。

 1.2Connection.On 监听

前面两篇中说过,服务端主动去发送消息给客户端,同时客户端也需要在建立连接后去监听的。

Connection.On支持泛型,Connection.On<Users>传入的泛型用于约束你将要接收的参数。

写法:Connection.On<string>("test", (msg) =>{MessageBox.Show(msg)});两个必填的参数,第一个是你要监听的方法的名称,第二个是action一个无返回值的委托,也就是你监听到后要做的操作。

这里有个隐藏的知识,看下面代码

服务端发送时的类和客户端监听时的类并不需要是同一个类,但是类中的字段需要相同,否则会监听不到,就好像你被重载了一样。 而利用这个泛型的好处就在于不用一个一个的传参数了,SignalR会主动帮你做序列化。不像websocket只能传输byte数组。

1.3Connection.InvokeAsync("")主动调用服务端的方法

通过它我们可以去发送消息,它主动调用服务端的方法,服务端接收后再通知其他客户端,同时被其他客户端监听到,就实现了发信息的功能。

写法:Connection.InvokeAsync("要调用的方法的名称",参数1,参数2,。。。);支持多参数传递,也可以通过泛型来约束你要调用的方法它所接收的参数类型:                Connection.InvokeAsync<Users>("hello","");这种在服务端的方法有重载的情况下就很好用

下面我们代码中,我们将监听的代码封装到了方法中,每个方法几乎都有需要传入一个action的委托,因为在这个静态类中我们不能确定哪个窗体有哪些控件,并且也无法获取到那些控件。所以把要做的操作通过调用的时候传入进来。

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows.Forms;
using ChatRommClient_WinFrom.Dtos;
using Microsoft.AspNetCore.SignalR.Client;

namespace ChatRommClient_WinFrom
{
    public static class  ChatService
    {
        public static long UserId = default;
        public static List<Users> UsersList = new List<Users>();
        public static HubConnection Connection;
        /// <summary>
        /// 初始化连接
        /// </summary>
        public static async void SignalRConnection()
        {
            Connection = new HubConnectionBuilder()
                .WithUrl("http://localhost:5160/chatHub")
                .Build();
            await Connection.StartAsync();
            Connection.Closed += async error =>
            {
                await Task.Delay(new Random().Next(0, 5) * 1000);
                await Connection.StartAsync();
            };
        }
        /// <summary>
        /// 监听好友上线
        /// </summary>
        public static void BuddysOnline(Action action)
        {
            Connection.On<Users>("BuddysOnline", user =>
            {
                Task.Run(() =>
                {
                    UsersList.Add(user);
                    action();
                    MessageBox.Show($"您的好友{user.NickName}上线了", "上线通知", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                });
            });
        }
        /// <summary>
        /// 监听接收消息
        /// </summary>
        /// <param name="action"></param>
        public static void ReceiveMessage(Action<string,DateTime> action)
        {
            //接收消息
            Connection.On<string,DateTime>("ReceiveMessage", (msg,sendTime) =>
            {
                Task.Run(() =>
                {
                    action(msg,sendTime);
                });
            });
        }
        /// <summary>
        /// 监听登录成功获取在线好友列表
        /// </summary>
        /// <param name="action"></param>
        public static void ReceiveBuddyList(Action action)
        {
            
            Connection.On<List<Users>>("ReceiveBuddyList", users =>
            {
                Task.Run(() =>
                {
                    UsersList.AddRange(users);
                    action();
                });
            });
        }
        /// <summary>
        /// 监听登录结果
        /// </summary>
        /// <param name="success"></param>
        /// <param name="error"></param>
        public static void ReceiveLoginResult(Action success,Action error)
        {
            Connection.On<bool,long>("LoginResult", (result,uid) =>
            {
                if (result)
                {
                    UserId = uid;
                    success();
                }
                else
                {
                    error();
                }
            });
        }
        /// <summary>
        /// 监听添加好友结果
        /// </summary>
        public static void ReceiveAddBuddyResult(Action action)
        {
            Connection.On<string>("ReceiveAddBuddyResult", msg =>
            {
                MessageBox.Show(msg);
                action();
            });
        }
    }

    public class Users
    {
        public string NickName { get; set; }
        public string ConnectionId { get; set; }
    }
}

二、登录界面

2.1初始化SignalR连接

程序启动时就开启连接,并开始监听登录结果这个方法

监听登录成功结果,我们需要传入两个方法,一个是登录成功后的操作,一个是失败的操作

 private void LoginSuccess()
        {
            MainFrm mainFrm = new MainFrm();
            mainFrm.Show();
            this.Visible = false;
        }

        private void LoginError()
        {
            MessageBox.Show("登录失败,账号或密码错误");
        }
private void LoginFrm_Load(object sender, EventArgs e)
        {
            //初始化连接
            ChatService.SignalRConnection();
            //监听登录的结果
            ChatService.ReceiveLoginResult(LoginSuccess,LoginError);
        }

在登录窗体点击注册按钮弹出注册的模态窗体

private void btn_registerFrom_Click(object sender, EventArgs e)
        {
            RegisterFrm frm = new RegisterFrm();
            frm.ShowDialog();
        }

2.2注册方法 

在注册界面点击注册时通过发送http请求,请求服务端写好的注册的api接口

 /// <summary>
        /// 注册
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void btn_register_Click(object sender, EventArgs e)
        {
            var userInfo = new
            {
                UserName=tb_userName.Text,
                NickName=tb_nickName.Text,
                PassWord=tb_pwd.Text
            };
            HttpClient client = new HttpClient();//创建客户端
            HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(userInfo));//请求的参数
            httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");//设置请求参数的格式
            var resMsg = client.PostAsync("http://localhost:5160/api/user/register", httpContent);//发出请求,接收返回值
            var result = await resMsg.Result.Content.ReadAsStringAsync();
            MessageBox.Show(result);
        }

 

 这个id呢就类似与qq号码这个东西,是由后端返回的,之后添加好友也需要通过这个id,其实呢你们可以在后端把id设为Guid类型的,我这里就用的int。

2.3登录方法

 上面我们写了监听,所以当登录成功后就会直接跳到主界面了。

private async void bt_login_Click(object sender, EventArgs e)
        {
            var uname = tb_userName.Text;
            var pwd = tb_pwd.Text;
           await ChatService.Connection.InvokeAsync("Login",uname,pwd);
        }

 成功:

 失败:

下一篇写发送消息和添加好友

源码地址:https://download.csdn.net/download/hyx1229/42548815 

需要免费源码的可以加.net core学习交流群:831181779,在群里@群主即可

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不想只会CRUD的猿某人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值