WebSocket,IsWebSocketRequest与AspNetWebSocketContext

asp.net新建一个服务端程序,用来处理链接服务端:

1,新建一个处理程序 .ashx

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.WebSockets;
using SFellowEntity.Models;

namespace SchoolfellowCard.Handler
{
    /// <summary>
    /// WebSocketServer webSocket服务
    /// </summary>
    public class WebSocketServer : IHttpHandler
    {
        //用户连接池
        private static Dictionary<string, WebSocket> connectPool = new Dictionary<string, WebSocket>();
        //离线消息池
        private static Dictionary<string, List<MessageInfo>> messagePool = new Dictionary<string, List<MessageInfo>>();

        public void ProcessRequest(HttpContext context)
        {
            if (context.IsWebSocketRequest)
            {
                context.AcceptWebSocketRequest(ProcessChat);
            } 
        }
        /// <summary>
        /// webSocket异步作业
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        private async Task ProcessChat(AspNetWebSocketContext context)
        {
            //WebSocket socket = context.WebSocket;
            //while (true)
            //{
            //    if (socket.State == WebSocketState.Open)
            //    {
            //        ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
            //        WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
            //        string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);
            //        userMsg = "你发送了:" + userMsg + "于" + DateTime.Now.ToLongTimeString();
            //        buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
            //        await socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
            //    }
            //    else
            //    {
            //        break;
            //    }
            //}
            WebSocket socket = context.WebSocket;
            string user =string.Format("{0}", context.QueryString["user"]);

            try
            {
                #region 验证用户添加连接池

                //第一次open时,添加到连接池中
                if (!connectPool.ContainsKey(user))
                {
                    connectPool.Add(user, socket); //不存在,添加
                }
                else
                {
                    if (socket != connectPool[user]) //当前对象不一致,更新
                    {
                        connectPool[user] = socket;
                    }
                }
                
                #endregion

                #region 离线消息处理
                if (messagePool.ContainsKey(user))
                {
                    //TODO:离线消息可放入数据库在此获取离线消息并返回给对应的用户
                    List<MessageInfo> msgs = messagePool[user];
                    foreach (MessageInfo item in msgs)
                    {
                        await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
                    }
                    messagePool.Remove(user);//移除离线消息
                    //TODO:处理完后标记离线消息已推送
                }
                #endregion

                string descUser = string.Empty;//目的用户
                while (true)
                {
                    if (socket.State == WebSocketState.Open)
                    {
                        ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
                        //websocket接收消息
                        WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);

                        #region 消息处理(字符截取、消息转发)
                        try
                        {
                            #region 关闭Socket处理,删除连接池
                            if (socket.State != WebSocketState.Open)//连接关闭
                            {
                                if (connectPool.ContainsKey(user)) connectPool.Remove(user);//删除连接池
                                break;
                            }
                            #endregion

                            string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
                            string[] msgList = userMsg.Split('|');
                            if (msgList.Length == 2)
                            {
                                if (msgList[0].Trim().Length > 0)
                                    descUser = msgList[0].Trim();//记录消息目的用户//TODO:将消息接收者可放入数据库存贮记录
                                buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
                            }
                            else
                                buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));

                            if (connectPool.ContainsKey(descUser))//判断客户端是否在线
                            {
                                WebSocket destSocket = connectPool[descUser];//目的客户端
                                if (destSocket != null && destSocket.State == WebSocketState.Open)
                                    await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
                            }
                            else
                            {
                                Task.Run(() =>
                                {
                                    if (!messagePool.ContainsKey(descUser))//将用户添加至离线消息池中
                                        messagePool.Add(descUser, new List<MessageInfo>());
                                    messagePool[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
                                    //TODO:离线消息插入数据库
                                });
                            }
                        }
                        catch (Exception exs)
                        {
                            //消息转发异常处理,本次消息忽略 继续监听接下来的消息
                        }
                        #endregion
                    }
                    else
                    {
                        break;
                    }
                }//while end
            }
            catch (Exception ex)
            {
                //整体异常处理
                if (connectPool.ContainsKey(user)) connectPool.Remove(user);
            }
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}

 

其中,MessageInfo.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SFellowEntity.Models
{
    /// <summary>
    /// 消息
    /// </summary>
    public class MessageInfo
    {
        /// <summary>
        /// 消息内容
        /// </summary>
        public ArraySegment<byte> MsgContent { get; set; }
        /// <summary>
        /// 消息时间
        /// </summary>
        public DateTime MsgTime { get; set; }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="msgTime"></param>
        /// <param name="msgContent"></param>
        public MessageInfo(DateTime msgTime, ArraySegment<byte> msgContent)
        {
            MsgTime = msgTime;
            MsgContent = msgContent;
        }
    }
}

 

 页面端:

2,页面JavaScript创建WebSocket对象,并发起连接

 

            $('#conn').click(function () {
                ws = new WebSocket('ws://' + window.location.hostname + ':' + window.location.port + '/Handler/WebSocketServer.ashx?user=' + $("#user").val());
                $('#msg').append('<p>正在连接</p>');

                ws.onopen = function () {
                    $('#msg').append('<p>已经连接</p>');
                }
                ws.onmessage = function (evt) {
                    $('#msg').append('<p>' + evt.data + '</p>');
                }
                ws.onerror = function (evt) {
                    $('#msg').append('<p>' + JSON.stringify(evt) + '</p>');
                }
                ws.onclose = function () {
                    $('#msg').append('<p>已经关闭</p>');
                }
            });

            $('#close').click(function () {
                ws.close();
            });

            $('#send').click(function () {
                if (ws.readyState == WebSocket.OPEN) {
                    ws.send($("#to").val() + "|" + $('#content').val());
                }
                else {
                    $('#tips').text('连接已经关闭');
                }
            });

 

posted @ 2022-10-26 19:29  熊仔其人  阅读(355)  评论(0编辑  收藏  举报