在IIS上搭建WebSocket服务器(二)

简介: 原文:在IIS上搭建WebSocket服务器(二)服务器端代码编写 1.新建一个ASP.net Web MVC5项目   2.新建一个“一般处理程序” 3.Handler1.ashx代码如下: using System; using System.
原文: 在IIS上搭建WebSocket服务器(二)

服务器端代码编写

1.新建一个ASP.net Web MVC5项目

 

2.新建一个“一般处理程序”

3.Handler1.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;


namespace WebApplicationWebsocketHandler
{
    /// <summary>
    /// 离线消息
    /// </summary>
    public class MessageInfo
    {
        public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
        {
            MsgTime = _MsgTime;
            MsgContent = _MsgContent;
        }
        public DateTime MsgTime { get; set; }
        public ArraySegment<byte> MsgContent { get; set; }
    }




    /// <summary>
    /// Handler1 的摘要说明
    /// </summary>
    public class Handler1 : IHttpHandler
    {
        private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
        private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
        public void ProcessRequest(HttpContext context)
        {
            //context.Response.ContentType = "text/plain";
            //context.Response.Write("Hello World");
            if (context.IsWebSocketRequest)
            {
                context.AcceptWebSocketRequest(ProcessChat);
            } 
        }

        private async Task ProcessChat(AspNetWebSocketContext context)
        {
            WebSocket socket = context.WebSocket;
            string user = context.QueryString["user"].ToString();

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

                #region 离线消息处理
                if (MESSAGE_POOL.ContainsKey(user))
                {
                    List<MessageInfo> msgs = MESSAGE_POOL[user];
                    foreach (MessageInfo item in msgs)
                    {
                        await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
                    }
                    MESSAGE_POOL.Remove(user);//移除离线消息
                }
                #endregion

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

                        #region 消息处理(字符截取、消息转发)
                        try
                        {
                            #region 关闭Socket处理,删除连接池
                            if (socket.State != WebSocketState.Open)//连接关闭
                            {
                                if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.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();//记录消息目的用户
                                buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
                            }
                            else
                                buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));

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


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

4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上

点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

 

目录
相关文章
|
监控 网络安全 调度
Quartz.Net整合NetCore3.1,部署到IIS服务器上后台定时Job不被调度的解决方案
解决Quartz.NET在.NET Core 3.1应用中部署到IIS服务器上不被调度的问题,通常需要综合考虑应用配置、IIS设置、日志分析等多个方面。采用上述策略,结合细致的测试和监控,可以有效地提高定时任务的稳定性和可靠性。在实施任何更改后,务必进行充分的测试,以验证问题是否得到解决,并监控生产环境的表现,确保长期稳定性。
1269 1
|
安全 C#
【Azure 应用服务】在安全漏洞扫描中发现有泄露服务器IIS版本的情况,如何实现屏蔽服务版本号信息呢?
【Azure 应用服务】在安全漏洞扫描中发现有泄露服务器IIS版本的情况,如何实现屏蔽服务版本号信息呢?
664 1
|
开发工具 开发者 Windows
Windows10 IIS Web服务器安装配置
Windows10 IIS Web服务器安装配置
427 2
|
前端开发 网络协议 物联网
Django Web:搭建Websocket服务器(入门篇)
Django Web:搭建Websocket服务器(入门篇)
2018 1
|
弹性计算 持续交付 Docker
阿里云云效产品使用合集之如何部署到阿里云服务器上的 Windows Server 上的 IIS
云效作为一款全面覆盖研发全生命周期管理的云端效能平台,致力于帮助企业实现高效协同、敏捷研发和持续交付。本合集收集整理了用户在使用云效过程中遇到的常见问题,问题涉及项目创建与管理、需求规划与迭代、代码托管与版本控制、自动化测试、持续集成与发布等方面。
|
8月前
|
网络安全 Windows
Windows IIS 10如何配置自签名SSL并实现自动跳转
本文记录了IIS配置自签名证书及HTTPS跳转的注意事项。包括解决443端口占用问题、URL Rewrite插件安装与配置、web.config修改方法,以及避免因旧教程导致的配置错误。
Windows IIS 10如何配置自签名SSL并实现自动跳转
|
网络协议
windows_server2012搭建iis并配置http重定向 iis转发
windows_server2012搭建iis并配置http重定向 iis转发
870 1
【Azure云服务 Cloud Service】如何在部署云服务Cloud Service时候通过启动任务Start Task来配置IIS (如开启ARR)
【Azure云服务 Cloud Service】如何在部署云服务Cloud Service时候通过启动任务Start Task来配置IIS (如开启ARR)
303 2
|
开发框架 .NET 中间件
【Azure 云服务】在Cloud Service的代码中如何修改IIS Application Pool的配置呢? 比如IdleTimeout, startMode, Recycling.PeriodicRestart.Time等
【Azure 云服务】在Cloud Service的代码中如何修改IIS Application Pool的配置呢? 比如IdleTimeout, startMode, Recycling.PeriodicRestart.Time等
274 0
【Azure 云服务】在Cloud Service的代码中如何修改IIS Application Pool的配置呢? 比如IdleTimeout, startMode, Recycling.PeriodicRestart.Time等
|
Windows
iis配置http重定向302转发get请求并去掉最后的斜杠/ iis重定向 iis去除url最后的斜杠 iis重定向链接斜杠(已解决)
iis配置http重定向302转发get请求并去掉最后的斜杠/ iis重定向 iis去除url最后的斜杠 iis重定向链接斜杠(已解决)
1068 0