From 2d3c116a3217ff1c5bd045fe05030737422a60c9 Mon Sep 17 00:00:00 2001 From: lxmou666 <772765102@qq.com> Date: Mon, 22 Feb 2021 14:44:47 +0800 Subject: [PATCH] =?UTF-8?q?=E8=81=8A=E5=A4=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- JianGongYun.sln | 14 +++ JianGongYun/App.config | 1 + JianGongYun/JianGongYun.csproj | 1 + JianGongYun/Properties/launchSettings.json | 2 +- JianGongYun/Style/TRTCResource.xaml | 2 +- JianGongYun/TRTC/LiveClassroom.cs | 43 ++++++- JianGongYun/TRTC/Models/ChatEntity.cs | 13 +++ JianGongYun/TRTC/Models/ClassroomEntity.cs | 4 + JianGongYun/TRTC/Utils/ChatItemBgConverter.cs | 22 ++++ .../TRTC/ViewModels/LiveWindowViewModel.cs | 8 +- JianGongYun/TRTC/Windows/LiveWindow.xaml | 61 +++++++++- JianGongYun/TRTC/Windows/LiveWindow.xaml.cs | 109 +++++++++++++++++- .../Windows/LiveWindowRightBottomBlock.xaml | 83 ++++++++++--- .../LiveWindowRightBottomBlock.xaml.cs | 31 ++++- JianGongYun/Views/Login.xaml.cs | 18 ++- WSDemo/Program.cs | 39 +++++++ WSDemo/WSDemo.csproj | 13 +++ 17 files changed, 428 insertions(+), 36 deletions(-) create mode 100644 JianGongYun/TRTC/Models/ChatEntity.cs create mode 100644 JianGongYun/TRTC/Utils/ChatItemBgConverter.cs create mode 100644 WSDemo/Program.cs create mode 100644 WSDemo/WSDemo.csproj diff --git a/JianGongYun.sln b/JianGongYun.sln index b21d04c..f9fc656 100644 --- a/JianGongYun.sln +++ b/JianGongYun.sln @@ -7,6 +7,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JianGongYun", "JianGongYun\ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClientDemo", "ClientDemo\ClientDemo.csproj", "{5C83270B-1086-494D-BCAF-0E773CC598AB}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WSDemo", "WSDemo\WSDemo.csproj", "{A748F095-84EF-4D1B-A1B1-842ADCD73D6C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -41,6 +43,18 @@ Global {5C83270B-1086-494D-BCAF-0E773CC598AB}.Release|x64.Build.0 = Release|Any CPU {5C83270B-1086-494D-BCAF-0E773CC598AB}.Release|x86.ActiveCfg = Release|Any CPU {5C83270B-1086-494D-BCAF-0E773CC598AB}.Release|x86.Build.0 = Release|Any CPU + {A748F095-84EF-4D1B-A1B1-842ADCD73D6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A748F095-84EF-4D1B-A1B1-842ADCD73D6C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A748F095-84EF-4D1B-A1B1-842ADCD73D6C}.Debug|x64.ActiveCfg = Debug|Any CPU + {A748F095-84EF-4D1B-A1B1-842ADCD73D6C}.Debug|x64.Build.0 = Debug|Any CPU + {A748F095-84EF-4D1B-A1B1-842ADCD73D6C}.Debug|x86.ActiveCfg = Debug|Any CPU + {A748F095-84EF-4D1B-A1B1-842ADCD73D6C}.Debug|x86.Build.0 = Debug|Any CPU + {A748F095-84EF-4D1B-A1B1-842ADCD73D6C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A748F095-84EF-4D1B-A1B1-842ADCD73D6C}.Release|Any CPU.Build.0 = Release|Any CPU + {A748F095-84EF-4D1B-A1B1-842ADCD73D6C}.Release|x64.ActiveCfg = Release|Any CPU + {A748F095-84EF-4D1B-A1B1-842ADCD73D6C}.Release|x64.Build.0 = Release|Any CPU + {A748F095-84EF-4D1B-A1B1-842ADCD73D6C}.Release|x86.ActiveCfg = Release|Any CPU + {A748F095-84EF-4D1B-A1B1-842ADCD73D6C}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/JianGongYun/App.config b/JianGongYun/App.config index d08a0bd..70c4087 100644 --- a/JianGongYun/App.config +++ b/JianGongYun/App.config @@ -6,5 +6,6 @@ + diff --git a/JianGongYun/JianGongYun.csproj b/JianGongYun/JianGongYun.csproj index 2276409..7144044 100644 --- a/JianGongYun/JianGongYun.csproj +++ b/JianGongYun/JianGongYun.csproj @@ -18,6 +18,7 @@ + diff --git a/JianGongYun/Properties/launchSettings.json b/JianGongYun/Properties/launchSettings.json index a4c6ce9..0613bfb 100644 --- a/JianGongYun/Properties/launchSettings.json +++ b/JianGongYun/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "JianGongYun": { "commandName": "Project", - "commandLineArgs": "sznykt://--classhead|测试课程1|--classsubhead|测试章节1|--teacherid|12345678|--teachername|王大锤", + "commandLineArgs": "sznykt://--classhead|测试课程1|--classsubhead|测试章节1|--teacherid|1234_5678|--teachername|王大锤|endtime|MjAyMS0wMy0xOCAyMTo1MDowMA==", "nativeDebugging": false } } diff --git a/JianGongYun/Style/TRTCResource.xaml b/JianGongYun/Style/TRTCResource.xaml index 8a0182c..de6d95f 100644 --- a/JianGongYun/Style/TRTCResource.xaml +++ b/JianGongYun/Style/TRTCResource.xaml @@ -71,7 +71,7 @@ - + diff --git a/JianGongYun/TRTC/LiveClassroom.cs b/JianGongYun/TRTC/LiveClassroom.cs index 949b0fa..110e284 100644 --- a/JianGongYun/TRTC/LiveClassroom.cs +++ b/JianGongYun/TRTC/LiveClassroom.cs @@ -21,6 +21,9 @@ using System.Diagnostics; using System.Runtime.InteropServices; using AduSkin.Controls.Metro; using System.Configuration; +using Websocket.Client; +using System.Windows.Threading; +using Newtonsoft.Json.Linq; namespace JianGongYun.TRTC { @@ -37,6 +40,7 @@ namespace JianGongYun.TRTC static string SDKAppKEY { get { return ConfigurationManager.AppSettings[nameof(SDKAppKEY)]; } } static uint LIVEAppID { get { return uint.Parse(ConfigurationManager.AppSettings[nameof(LIVEAppID)]); } } static uint LIVEBizid { get { return uint.Parse(ConfigurationManager.AppSettings[nameof(LIVEBizid)]); } } + static string WSUrl { get { return ConfigurationManager.AppSettings[nameof(WSUrl)]; } } /// /// TRTC实例 @@ -53,10 +57,18 @@ namespace JianGongYun.TRTC /// /// 直播窗口 /// - public static Window CurrentLiveWindow; + public static LiveWindow CurrentLiveWindow; private static LiveWindowViewModel liveWinMode; public static ClassroomEntity CurrentClassroomEntity { get; private set; } public static TRTCCloudCallback TRTCCloudCallback = new TRTCCloudCallback(); + + /// + /// ws客户端 + /// + public static WebsocketClient WSClient = null; + public static DispatcherTimer Heartbeat = null; + public static string ClassId = null;//章节id + /// /// 摄像头帧 /// @@ -121,6 +133,30 @@ namespace JianGongYun.TRTC _RecoderDir = $"{classroomEntity.ClassHead}_{classroomEntity.ClassSubHead}"; + //连接WS + if (WSClient != null && WSClient.IsRunning)//只连一个 + { + WSClient.Stop(System.Net.WebSockets.WebSocketCloseStatus.NormalClosure, "connect repeat"); + WSClient.Dispose(); + } + + var url = new Uri(WSUrl); + WSClient = new WebsocketClient(url); + WSClient.ReconnectTimeout = TimeSpan.FromSeconds(30); + WSClient.ReconnectionHappened.Subscribe(info => + Console.WriteLine($"Reconnection happened, type: {info.Type}")); + + WSClient.MessageReceived.Subscribe(CurrentLiveWindow.OnMsg); + WSClient.Start(); + ClassId = CurrentClassroomEntity.TeacherId.Split('_')[1]; + WSClient.Send($"{{code:10000,nick:\"{CurrentClassroomEntity.TeacherName}\",\"room\":\"push_{ClassId}\"}}");//进房间 + + //发送心跳包 + Heartbeat = new DispatcherTimer(DispatcherPriority.Render); + Heartbeat.Interval = TimeSpan.FromSeconds(5); + Heartbeat.Tick += new EventHandler((a, b) => WSClient.Send("{code:10016}")); + Heartbeat.Start(); + callerWindow?.Hide();//隐藏调用窗口 CurrentLiveWindow.Show(); } @@ -744,6 +780,11 @@ namespace JianGongYun.TRTC CurrentLiveWindow = null; CurrentClassroomEntity = null; + Heartbeat.Stop(); + WSClient.Stop(System.Net.WebSockets.WebSocketCloseStatus.NormalClosure, "end"); + WSClient.Dispose(); + WSClient = null; + Heartbeat = null; lTXDeviceManager.Dispose(); lTXDeviceManager = null; diff --git a/JianGongYun/TRTC/Models/ChatEntity.cs b/JianGongYun/TRTC/Models/ChatEntity.cs new file mode 100644 index 0000000..60c6fc7 --- /dev/null +++ b/JianGongYun/TRTC/Models/ChatEntity.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JianGongYun.TRTC.Models +{ + public class ChatEntity + { + public string Body { get; set; } + public string Nick { get; set; } + public string Date { get; set; } + } +} diff --git a/JianGongYun/TRTC/Models/ClassroomEntity.cs b/JianGongYun/TRTC/Models/ClassroomEntity.cs index 7b2b44d..44d7730 100644 --- a/JianGongYun/TRTC/Models/ClassroomEntity.cs +++ b/JianGongYun/TRTC/Models/ClassroomEntity.cs @@ -25,6 +25,10 @@ namespace JianGongYun.TRTC.Models /// 章节名称 /// public string ClassSubHead { get; set; } + /// + /// 结束时间 + /// + public DateTime? EndTime { get; set; } } } diff --git a/JianGongYun/TRTC/Utils/ChatItemBgConverter.cs b/JianGongYun/TRTC/Utils/ChatItemBgConverter.cs new file mode 100644 index 0000000..70d680d --- /dev/null +++ b/JianGongYun/TRTC/Utils/ChatItemBgConverter.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; +using System.Windows.Data; +using System.Windows.Media; + +namespace JianGongYun.TRTC +{ + public class ChatItemBgConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return value == null ? new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)) : parameter; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return null; + } + } +} diff --git a/JianGongYun/TRTC/ViewModels/LiveWindowViewModel.cs b/JianGongYun/TRTC/ViewModels/LiveWindowViewModel.cs index 1af180a..4808041 100644 --- a/JianGongYun/TRTC/ViewModels/LiveWindowViewModel.cs +++ b/JianGongYun/TRTC/ViewModels/LiveWindowViewModel.cs @@ -28,7 +28,7 @@ namespace JianGongYun.TRTC.ViewModels /// /// 学生总数 /// - private int _StudentCount = 1; + private int _StudentCount = 0; public int StudentCount { set @@ -356,15 +356,15 @@ namespace JianGongYun.TRTC.ViewModels /// /// 消息集合 /// - private ObservableCollection _Chats = new ObservableCollection() { "1", "2" }; - public ObservableCollection Chats + private ObservableCollection _Chats = new ObservableCollection(); + public ObservableCollection Chats { set { _Chats = value; if (PropertyChanged != null) { - PropertyChanged(this, new PropertyChangedEventArgs("Chats"));//对StudentCount进行监听 + PropertyChanged(this, new PropertyChangedEventArgs("Chats")); } } get diff --git a/JianGongYun/TRTC/Windows/LiveWindow.xaml b/JianGongYun/TRTC/Windows/LiveWindow.xaml index 6aaa5a9..0ce8c15 100644 --- a/JianGongYun/TRTC/Windows/LiveWindow.xaml +++ b/JianGongYun/TRTC/Windows/LiveWindow.xaml @@ -62,7 +62,7 @@ - + 直播中 @@ -70,7 +70,63 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -205,6 +261,7 @@ 请选择要分享的屏幕或前台窗口(上课期间可随时切换) + diff --git a/JianGongYun/TRTC/Windows/LiveWindow.xaml.cs b/JianGongYun/TRTC/Windows/LiveWindow.xaml.cs index 1e276ee..2bb6637 100644 --- a/JianGongYun/TRTC/Windows/LiveWindow.xaml.cs +++ b/JianGongYun/TRTC/Windows/LiveWindow.xaml.cs @@ -16,6 +16,9 @@ using System.Windows.Threading; using JianGongYun.TRTC.Components; using System.Runtime.InteropServices; using System.ComponentModel; +using Websocket.Client; +using Newtonsoft.Json.Linq; +using System.Diagnostics; namespace JianGongYun.TRTC.Windows { @@ -34,15 +37,80 @@ namespace JianGongYun.TRTC.Windows InitializeComponent(); this.Icon = new BitmapImage(new Uri("logo.ico", UriKind.RelativeOrAbsolute)); NoticeManager.Initialize(); - //AttachConsole(-1);//把进程挂在控制台,通过命令行启动程序可以看到控制台输出 + AttachConsole(-1);//把进程挂在控制台,通过命令行启动程序可以看到控制台输出 LiveWindowViewModel = new ViewModels.LiveWindowViewModel(); SettingWindowViewModel = ViewModels.SettingWindowViewModel.GetInstance(); this.DataContext = LiveWindowViewModel; BorderBrush = new SolidColorBrush(color: Color.FromRgb(42, 43, 48));//窗口标题背景颜色 + + for (int i = 0; i < 12; i++) + { + LiveWindowViewModel.Chats.Add(new Models.ChatEntity());//放几个空聊天数据占位置 + } + Loaded += LiveWindowRightBottomBlock_Loaded1; + } + private void LiveWindowRightBottomBlock_Loaded1(object sender, RoutedEventArgs e) + { + if (ChatList.Items.Count > 0) + { + ChatList.ScrollIntoView(ChatList.Items[ChatList.Items.Count - 1]); + } } - - + /// + /// ws消息 + /// + /// + public void OnMsg(ResponseMessage msg) + { + Debug.Print(msg.Text); + Console.WriteLine($"Message received: {msg}"); + if (msg.MessageType == System.Net.WebSockets.WebSocketMessageType.Text) + { + var data = JObject.Parse(msg.Text); + var temp = data.SelectToken("extend.code"); + if (temp != null) + { + var code = temp.ToObject(); + switch (code) + { + case 20001: + var count = data.SelectToken("extend.mess").ToObject(); + LiveWindowViewModel.StudentCount = count; + break; + case 30004://心跳包返回的时间 + if (DateTime.TryParse(data.SelectToken("extend.date").ToObject(), out var date)) + { + if (date > LiveClassroom.CurrentClassroomEntity.EndTime)//结束时间关闭直播 + { + this.Dispatcher.Invoke(new Action(() => + { + AduMessageBox.ShowOK("已到结束时间", "提醒", "确定"); + StartLive_Click(stoplive, null); + })); + } + } + break; + } + return; + } + temp = data.SelectToken("body"); + if (temp != null)//发送消息后服务器的返回 + { + var body = data["body"].ToString(); + var nick = data["extend"]["nick"].ToString(); + var time = data["extend"]["time"].ToString(); + this.Dispatcher.Invoke(new Action(() => + { + if (LiveWindowViewModel.Chats.Count > 520) + { + LiveWindowViewModel.Chats.RemoveAt(0); + } + LiveWindowViewModel.Chats.Add(new Models.ChatEntity { Body = body, Nick = nick, Date = time }); + })); + } + } + } protected override void OnActivated(EventArgs e) { @@ -362,5 +430,40 @@ namespace JianGongYun.TRTC.Windows this.Hide(); blockTop.Show(); } + + public void SendMsg(TextBox text) + { + if (!string.IsNullOrEmpty(text.Text)) + { + //LiveWindow.LiveWindowViewModel.Chats.Add(new Models.ChatEntity { Body = text.Text });//往Chats集合添加数据会自动更新到界面上 + LiveClassroom.WSClient.Send($"{{\"code\":10086,\"mess\":\"{text.Text}\",\"room\":\"push_{LiveClassroom.ClassId}\"}}"); + text.Text = ""; + } + } + + private void Button_PreviewKeyDown(object sender, KeyEventArgs e) + { + //输入框回车 + if (e.Key == Key.Enter) + { + SendMsg(ChatIpt); + } + } + + private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e) + { + + //输入框回车 + if (e.Key == Key.Enter) + { + var text = (TextBox)sender; + SendMsg(text); + } + } + + private void Button_Click(object sender, RoutedEventArgs e) + { + SendMsg(ChatIpt); + } } } diff --git a/JianGongYun/TRTC/Windows/LiveWindowRightBottomBlock.xaml b/JianGongYun/TRTC/Windows/LiveWindowRightBottomBlock.xaml index 7d7ba8c..519bfe6 100644 --- a/JianGongYun/TRTC/Windows/LiveWindowRightBottomBlock.xaml +++ b/JianGongYun/TRTC/Windows/LiveWindowRightBottomBlock.xaml @@ -4,6 +4,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:JianGongYun.TRTC.Windows" + xmlns:System="clr-namespace:System;assembly=mscorlib" mc:Ignorable="d" ResizeMode="NoResize" ShowInTaskbar="False" @@ -12,22 +13,26 @@ AllowsTransparency="True" Background="Transparent" MouseDown="Window_MouseDown" + xmlns:live="clr-namespace:JianGongYun.TRTC" Title="" Height="600" Width="200"> + 9 + + 35 + 5 + + + + + + + + + + - - - - + + @@ -62,14 +72,53 @@ - + - - + + - + + + + + + + + + + + + + + + + + + diff --git a/JianGongYun/TRTC/Windows/LiveWindowRightBottomBlock.xaml.cs b/JianGongYun/TRTC/Windows/LiveWindowRightBottomBlock.xaml.cs index c7f8ab2..661f8e4 100644 --- a/JianGongYun/TRTC/Windows/LiveWindowRightBottomBlock.xaml.cs +++ b/JianGongYun/TRTC/Windows/LiveWindowRightBottomBlock.xaml.cs @@ -15,6 +15,21 @@ using System.Windows.Shapes; namespace JianGongYun.TRTC.Windows { + public class ScrollingListBox : ListBox + { + protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + { + if (e.NewItems == null) return; + var newItemCount = e.NewItems.Count; + + if (newItemCount > 0) + this.ScrollIntoView(e.NewItems[newItemCount - 1]); + + base.OnItemsChanged(e); + } + } + + /// /// LiveWindowRightBottomBlock.xaml 的交互逻辑 /// @@ -40,6 +55,16 @@ namespace JianGongYun.TRTC.Windows this.Top += 100; Loaded += LiveWindowRightBottomBlock_Loaded; } + + Loaded += LiveWindowRightBottomBlock_Loaded1; + } + + private void LiveWindowRightBottomBlock_Loaded1(object sender, RoutedEventArgs e) + { + if (ChatList.Items.Count > 0) + { + ChatList.ScrollIntoView(ChatList.Items[ChatList.Items.Count - 1]); + } } private void LiveWindowRightBottomBlock_Loaded(object sender, RoutedEventArgs e) @@ -56,6 +81,7 @@ namespace JianGongYun.TRTC.Windows PreVideoWrap.Children.Add(view); view.SetPause(false); } + } protected override void OnClosing(CancelEventArgs e) @@ -90,10 +116,9 @@ namespace JianGongYun.TRTC.Windows if (e.Key == Key.Enter) { var text = (TextBox)sender; - //socket.send(text.Text); - LiveWindow.LiveWindowViewModel.Chats.Add(text.Text);//往Chats集合添加数据会自动更新到界面上 - text.Text = ""; + LiveWindow.SendMsg(text); } } + } } diff --git a/JianGongYun/Views/Login.xaml.cs b/JianGongYun/Views/Login.xaml.cs index 82b001a..bed0d21 100644 --- a/JianGongYun/Views/Login.xaml.cs +++ b/JianGongYun/Views/Login.xaml.cs @@ -27,11 +27,12 @@ namespace JianGongYun.Views const string CLASS_SUB_HEAD = "--classsubhead"; const string TEACHER_ID = "--teacherid"; const string TEACHER_NAME = "--teachername"; + const string END_TIME = "endtime"; public Login() { InitializeComponent(); this.Icon = new BitmapImage(new Uri("logo.ico", UriKind.Relative)); - string errMsg = "", classHead = default, classSubHead = default, teacherId = default, teacherName = default; + string errMsg = "", classHead = default, classSubHead = default, teacherId = default, teacherName = default, endtime = default; var urltemps = Environment.GetCommandLineArgs(); if (urltemps.Length < 2) { @@ -44,7 +45,7 @@ namespace JianGongYun.Views errMsg = "Startup Parameter Error"; goto Skip; } - var args= HttpUtility.UrlDecode(first, Encoding.UTF8).Replace("://","|").Split("|"); + var args = HttpUtility.UrlDecode(first, Encoding.UTF8).Replace("://", "|").Split("|"); int indexTemp = Array.IndexOf(args, CLASS_HEAD); if (indexTemp < 0) { @@ -77,7 +78,15 @@ namespace JianGongYun.Views } teacherName = args[indexTemp + 1]; - Skip: + indexTemp = Array.IndexOf(args, END_TIME); + if (indexTemp < 0) + { + errMsg = $"{nameof(END_TIME)} NULL"; + goto Skip; + } + endtime = args[indexTemp + 1]; + + Skip: if (!string.IsNullOrWhiteSpace(errMsg)) { MessageBox.Show(errMsg, "错误", MessageBoxButton.OKCancel, MessageBoxImage.Error); @@ -90,7 +99,8 @@ namespace JianGongYun.Views ClassHead = classHead, ClassSubHead = classSubHead, TeacherId = teacherId, - TeacherName = teacherName + TeacherName = teacherName, + EndTime = string.IsNullOrEmpty(endtime) ? null : new DateTime?(DateTime.Parse(Encoding.UTF8.GetString(Convert.FromBase64String(endtime)))) }); } } diff --git a/WSDemo/Program.cs b/WSDemo/Program.cs new file mode 100644 index 0000000..827db0b --- /dev/null +++ b/WSDemo/Program.cs @@ -0,0 +1,39 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using Websocket.Client; + +namespace WSDemo +{ + class Program + { + static void Main(string[] args) + { + var exitEvent = new ManualResetEvent(false); + var url = new Uri("wss://web.cqjgjyw.cn/websocket"); + + using (var client = new WebsocketClient(url)) + { + client.ReconnectTimeout = TimeSpan.FromSeconds(30); + client.ReconnectionHappened.Subscribe(info => + Console.WriteLine($"Reconnection happened, type: {info.Type}")); + + client.MessageReceived.Subscribe(msg => Console.WriteLine($"Message received: {msg}")); + client.StartOrFail(); + + Task.Run(() => client.Send("{code:10000,nick:\"张三\",\"room\":\"push_5678\"}")); + Task.Run(() => + { + while (true) + { + client.Send($"{{\"code\":10086,\"mess\":\"{Guid.NewGuid()}\",\"room\":\"push_5678\"}}"); + client.Send("{code:10016}"); + Thread.Sleep(5000); + } + }); + + exitEvent.WaitOne(); + } + } + } +} diff --git a/WSDemo/WSDemo.csproj b/WSDemo/WSDemo.csproj new file mode 100644 index 0000000..f5e75b9 --- /dev/null +++ b/WSDemo/WSDemo.csproj @@ -0,0 +1,13 @@ + + + + Exe + netcoreapp3.1 + + + + + + + +