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

服務器端代碼編寫服務器

1.新建一個ASP.net Web MVC5項目socket

 

2.新建一個「通常處理程序」async

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的系統時不能夠的)上spa

點擊「生成」->"發佈........",以文件系統的方式發佈,目標位置爲咱們建立的IIS網站對應的物理路徑.net

相關文章
相關標籤/搜索