wbSocket

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
    <title></title>
    <script src="js/jquery-3.2.1.min.js"></script>
    <script>
        var ws;
        $().ready(function () {
            $('#conn').click(function () {
                ws = new WebSocket('ws://localhost:4498/test2.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('连接已经关闭');
                }
            });

        });
    </script>
</head>
<body>
    <div>
        <input id="user" type="text" value="xx" />
        <input id="conn" type="button" value="连接" />
        <input id="close" type="button" value="关闭" /><br />
        <span id="tips"></span>
        <input id="content" type="text" value="txt" />
        <input id="send" type="button" value="发送" /><br />
        <input id="to" type="text" value="xx" />目的用户
        <div id="msg">
        </div>
    </div>
</body>
</html>

  

<%@ WebHandler Language="C#" Class="test2" %>

using System;
using System.Web;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net.WebSockets;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.WebSockets;
public class test2 : IHttpHandler
{
    /// <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; }
    }

    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)
    {
        if (context.IsWebSocketRequest)
        {
            context.AcceptWebSocketRequest(ProcessChat);
        }
        else
        {
            context.Response.ContentType = "text/plain";
            context.Response.Write("Hello World"+DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff"));
        }
    }

    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;
        }
    }


}

  

http://www.cnblogs.com/cemaster/p/6006510.html

原文地址:https://www.cnblogs.com/xiangxiong/p/7552793.html