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('连接已经关闭');
- }
- });
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |