C#版Websocket服务端实例

Socket服务类代码

  1     public class SocketSendHelper
  2     {
  4         //实例
  5         private static SocketSendHelper _ins;
  6         public static SocketSendHelper Ins => _ins ?? (_ins = new SocketSendHelper());
  7         /// <summary>
  8         /// 边界锁
  9         /// </summary>
 10         private static object SocketsLockFlag = new object();
 11         /// <summary>
 12         /// 所有Socket连接
 13         /// </summary>
 14         List<WebSocketModel> Sockets = new List<WebSocketModel>();
 15         /// <summary>
 16         /// 启动Socket发送信息服务
 17         /// </summary>
 18         public void StartSocketSend()
 19         {
 20             //获取配置
 21             var sendSocketLink= GetSocketSendLink();
 22             //初始化服务
 23             var server = new WebSocketServer(sendSocketLink);
 24             //配置日志级别
 25             FleckLog.Level = LogLevel.Error;
 26             //建立连接
 27             server.Start(socket =>
 28             {
 29                 socket.OnOpen = () =>
 30                 {
 31 
 32                     lock (SocketsLockFlag)
 33                     {
 34                         Console.WriteLine("OnOpen访客 :{0} 请求打开", socket.ConnectionInfo.ClientPort);
 35                         //将每个建立Socket连接的实例添加到WebSocketModel容器内。
 36                         //如果出现异常断电等特殊情况,WebSocketModel内的socket实例可能会出现重复
 37                         Sockets.Add(new WebSocketModel()
 38                         {
 39                             Socket = socket
 40                         });
 41                     }
 42                 };
 43                
 44                 socket.OnClose = () =>
 45                 {
 46                     lock (SocketsLockFlag)
 47                     {
 48                         //查询当前Socket
 49                         var webSocketModel = Sockets.FirstOrDefault(v => v.Socket == socket);
 50                         if (webSocketModel == null)
 51                             return;
 52                         //#region 业务代码,将要关闭的Socket客户端(这里是用户信息也可以是其他信息)信息返回给客户端,便于客户端移除当前socket
 53                         ////webSocketModel内socket实例为启动Socket的OnOpen委托添加,userInfo为接收信息时的OnMessage委托添加
 54                         //var json = JsonConvert.SerializeObject(webSocketModel.userInfo);
 55                         ////将关闭的socket用户信息发回客户端
 56                         //socket.Send(json);
 57                         ////从webSocketModel内移除当前socket的所有实例,正常只有一个,兼容处理
 58                         //foreach (var item in Sockets)
 59                         //{
 60                         //    if (item.Socket == socket)
 61                         //        Sockets.Remove(item);
 62                         //}
 63                         //#endregion
 64                         //发送关闭socket的用户信息给客户端
 65                         SendCloseOrErrorSocketUserInfoToClient(webSocketModel);
 66                         //从Sockets移除当前socket所有实例
 67                         Sockets.Remove(webSocketModel);
 68 
 69                         //当连接出现意外中断或中断时
 70                         Console.WriteLine("OnClose访客 :{0} 请求断开,访客信息:{1}", socket.ConnectionInfo.ClientPort, JsonConvert.SerializeObject(webSocketModel.userInfo));
 71 
 72                     }
 73                 };
 74 
 75                 socket.OnError = (ex) =>
 76                 {
 77                     Console.WriteLine("Socket连接出现错误:{0},网络可能正在切换中!", ex.Message);
 78                     lock (SocketsLockFlag)
 79                     {
 80                         var webSocketModel = Sockets.FirstOrDefault(v => v.Socket == socket);
 81                         if (webSocketModel == null)
 82                             return;
 83                         //发送报错socket的用户信息给客户端
 84                         SendCloseOrErrorSocketUserInfoToClient(webSocketModel);
 85                         //从Sockets移除当前socket所有实例
 86                         Sockets.Remove(webSocketModel);
 87 
 88                         //当连接出现意外中断或中断时
 89                         Console.WriteLine("OnClose访客 :{0} 请求断开,访客信息:{1}", socket.ConnectionInfo.ClientPort,JsonConvert.SerializeObject(webSocketModel.userInfo));
 90 
 91                     }
 92                 };
 93 
 94                 socket.OnMessage = message =>
 95                 {
 96                     ForwardStuentToBigScreen(message, socket);
 97                 };
 98             });
 99         }
100         /// <summary>
101         /// 获取Socket发送连接
102         /// </summary>
103         /// <returns></returns>
104         public string GetSocketSendLink()
105         {
106             ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
107             configurationBuilder.AddJsonFile("config.json", optional: false, reloadOnChange: false);
108             IConfigurationRoot config = configurationBuilder.Build();
109             var sendSocketLink = config.GetSection("Socket:SendSocketLink").Value;
110             Console.WriteLine($"socket地址:{sendSocketLink}");
111             return sendSocketLink;
112         }
113         /// <summary>
114         /// 发送关闭socket或报错socket的用户信息给客户端
115         /// </summary>
116         /// <param name="webSocketModel"></param>
117         public void SendCloseOrErrorSocketUserInfoToClient(WebSocketModel webSocketModel)
118         {
119             #region 业务代码,将要关闭的Socket客户端(这里是用户信息也可以是其他信息)信息返回给客户端,便于客户端移除当前socket
120             //webSocketModel内socket实例为启动Socket的OnOpen委托添加,userInfo为接收信息时的OnMessage委托添加
121             var json = JsonConvert.SerializeObject(webSocketModel.userInfo);
122             //将关闭的socket用户信息发回客户端
123             webSocketModel.Socket.Send(json);
124             
125             #endregion
126         }
127         ///// <summary>
128         ///// 从Sockets移除当前socket所有实例
129         ///// </summary>
130         //public void RemoveCurSocketFromWebSocketModel(WebSocketModel webSocketModel)
131         //{
132         //    //从webSocketModel内移除当前socket的所有实例,正常只有一个,兼容处理
133         //    List<WebSocketModel> socketsDeepCopy = new List<WebSocketModel>(Sockets.ToArray());
134         //    foreach (var item in socketsDeepCopy)
135         //        {
136         //            if (item.Socket == webSocketModel.Socket)
137         //                Sockets.Remove(item);
138         //        }
139         //}     
140         /// <summary>
141         /// 转发学生端信息到大屏
142         /// </summary>
143         /// <param name="message"></param>
144         /// <param name="socket"></param>
145         public void ForwardStuentToBigScreen(string message, IWebSocketConnection socket)
146         {
147             WebSocketModel webSocketModel = null;
148 
149             lock (SocketsLockFlag)
150             {
151                 webSocketModel = Sockets.FirstOrDefault(v => v.Socket == socket);
152 
153                 if (webSocketModel == null)
154                     return;
155                 #region 保存客户端发送的用户信息
156                 var dynamicData = JsonConvert.DeserializeObject<dynamic>(message);
157                 if (dynamicData == null)
158                 {
159                     Console.WriteLine("请求Message:{0}格式错误", message);
160                     return;
161                 }
162                 webSocketModel.userInfo.ClientId = dynamicData.ClientId;
163                 webSocketModel.userInfo.UserId = dynamicData.UserId;
164                 webSocketModel.userInfo.ProtocolType = dynamicData.ProtocolType;
165                 #endregion
166                 //如果客户端为学生端,将信息转发大屏
167                 if (webSocketModel.userInfo.ClientId != "BigScreenClient")
168                 {
169                    
170                     SendMsg(message);
171                 }
172             }
173 
174         }
175 
176         /// <summary>
177         /// 根据传入WebSocket的类型,在已建立的封装的Socket model中查找是否有该枚举类型,如果有则发送信息
178         /// </summary>
179         /// <param name="type">Socket发送的枚举类型</param>
180         /// <param name="data">实体数据</param>
181         public void SendMsg(string data)
182         {
183             lock (SocketsLockFlag)
184             {
185                 var bigScreenSocket = Sockets.Where(v => v.Socket.IsAvailable && v.userInfo?.ClientId == "BigScreenClient").FirstOrDefault();
186                 //var bigScreenSocket = Sockets.Where(v => v.Socket.IsAvailable ).FirstOrDefault();
187                 if (bigScreenSocket != null)
188                     bigScreenSocket.Socket.Send(data);
189             }
190         }
191 
192 
193     }

调用代码

 1 SocketSendHelper.Ins.StartSocketSend(); 2 SocketSendHelper.Ins.SendMsg("1111"); 

参考地址:https://www.cnblogs.com/zhangwei595806165/p/4791589.html

posted @ 2023-04-13 14:32  Fast & Furious  阅读(372)  评论(0)    收藏  举报