服务器端代码编写 1.新建一个ASP.net Web MVC5项目 - w8 d( ^1 y5 Q- ^) X5 \0 A
2.新建一个“一般处理程序” 3.Handler1.ashx代码如下: - using System;
2 n4 ~- j5 N! {1 n1 N8 | - using System.Collections.Generic;
' e: F, P; x8 y0 Y( L- s9 M - using System.Linq;& c" D1 Y Q! B ?: M
- using System.Net.WebSockets;# r+ e6 L2 Z- L8 F
- using System.Text;
. |9 \. w2 [0 P+ g - using System.Threading;' s" y- Y6 c. \
- using System.Threading.Tasks;3 z7 j6 W8 Q& W7 X. ~" V' Z
- using System.Web;9 |5 u! t I4 o+ V0 D4 k( r' {6 e
- using System.Web.WebSockets;
8 y2 P, d- U8 q
9 B) O' _$ e; O& W0 G
& b$ ]* {, p B; z- namespace WebApplicationWebsocketHandler
' B5 T+ ]# q+ C- t1 l - {
8 g2 E; h* O, t: {3 F. _0 N0 Q - /// <summary>- p. W# K0 V" _7 W, s# }
- /// 离线消息
* I, D* C% @0 p& R: | c% J - /// </summary>) M) c. c% a+ N3 M/ O! u) Y- L
- public class MessageInfo; K: x- Q* h# h; V
- {
, w/ E! f- k' W3 a/ Z; H - public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)7 ~, Z( }0 s, e! L
- {
) p- u) y' o: f' D" F* I - MsgTime = _MsgTime;
* }2 R! M6 ?8 ]3 ~5 s* w( h, m - MsgContent = _MsgContent;( ]: Y- t0 @3 d! c* K
- }6 W: K# ^# I/ r" b2 a; f4 O
- public DateTime MsgTime { get; set; }
4 I1 F( O1 m& k" j3 k - public ArraySegment<byte> MsgContent { get; set; }2 s N5 r) v# O/ E4 ]# a
- }# R7 y- D: G' @" \7 B' }
" Q' h3 n" F- V- " `# B# N- T( @7 _' y) b
3 o1 \; r! e; A+ _
5 c! X( Q4 V* N* j& n- /// <summary>" K; M! i- w- }) U( u1 w. u6 Z
- /// Handler1 的摘要说明2 H7 N b- J- @
- /// </summary># n3 b2 v+ e$ K. ?, D0 w! @
- public class Handler1 : IHttpHandler8 D5 _6 N, U! d: s ]; f" G4 {
- {
7 Z4 `1 ^' u) n ] - private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池3 [5 z( l# q7 f0 `2 X; Z+ B
- private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池+ `' C' m8 L. x% J1 Y
- public void ProcessRequest(HttpContext context)
4 X: h; \! d' x5 g& l3 j- m* [ - {
( |. O8 _6 p! O0 ?0 a - //context.Response.ContentType = "text/plain";
( f: ?, P4 z3 W- H/ t9 Z& x( q9 x - //context.Response.Write("Hello World");
; ^ y" k+ u$ O' W$ U - if (context.IsWebSocketRequest)) I6 {; U; c H4 p: c* ~, x- q
- {
2 ?; W. L4 G. y7 \ - context.AcceptWebSocketRequest(ProcessChat);$ M8 P/ e0 v! I" R
- }
8 b$ {. h) K) o/ f5 I' |6 S; v - }
/ I7 L% H6 l1 J( e7 G - ; D! J3 t0 Y8 q6 z- E! J
- private async Task ProcessChat(AspNetWebSocketContext context)
+ ?0 A/ Y* t! z - {9 q) p0 X8 m0 Q7 c% c7 ^0 D9 p. o, R
- WebSocket socket = context.WebSocket;: l1 |7 @' C+ F: W9 q
- string user = context.QueryString["user"].ToString();
* [+ q9 q; S3 @. \
) @$ H' h/ J3 b* R5 G- try( d, m- W7 u1 p* K$ [
- {# U6 s% s& C# W2 H; E1 Q4 W3 {
- #region 用户添加连接池) V0 H: g. m5 J$ [/ ]6 T
- //第一次open时,添加到连接池中" N$ {3 p8 G$ \( V" O" n
- if (!CONNECT_POOL.ContainsKey(user))/ c( I: o* d& H+ e U
- CONNECT_POOL.Add(user, socket);//不存在,添加 D+ i1 g& y) Q" Z3 F D
- else
1 I) f/ x0 [: {% I/ i' d* S& o8 R1 ? - if (socket != CONNECT_POOL[user])//当前对象不一致,更新/ D3 N, W$ g4 t; E5 s- ]2 B
- CONNECT_POOL[user] = socket;
6 F' w9 b) C6 D0 o - #endregion% H( w% ?/ d# E( y1 {6 [7 g6 \
- 5 E3 R3 j% P Z" Q% X4 W( V! N% i
- #region 离线消息处理
/ i3 V: `# y" E" W2 B- Y+ P - if (MESSAGE_POOL.ContainsKey(user))5 r1 |: i1 s$ p8 [/ c
- {1 q/ s) D6 t3 n" h$ W" a+ y( [
- List<MessageInfo> msgs = MESSAGE_POOL[user];
! H/ j0 k4 Q* ~1 X# z. j: G - foreach (MessageInfo item in msgs)
, p; J6 N0 H3 y* {: Z) @ - {
! V# P/ x/ R, v2 Y i7 p0 v - await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
5 y% \5 _6 a; @/ @ Y - }& P) x2 k; U9 U: E$ q5 a, q3 Q1 U
- MESSAGE_POOL.Remove(user);//移除离线消息
2 a, Y% F( S {+ \* } - }' r& p" `7 e9 ]5 x* y
- #endregion
{ S2 v; W- K) L1 p( R - % i* \; J# _( X% b
- string descUser = string.Empty;//目的用户
9 ^. Z1 ]1 @5 C - while (true)
. _8 y$ o# e6 v- ` - {
, d3 T4 o; ^2 ?# O% a0 W( F - if (socket.State == WebSocketState.Open)
( e. ^. v' |; v/ i5 u+ U3 x - {+ r' }( U. ]; o2 H! A
- ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);$ v* O8 K, u8 G6 |
- WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);. ^- Y- Z U$ N9 ^
- 0 N. x: D& W+ g
- #region 消息处理(字符截取、消息转发)1 K6 ] |, i( X! H4 {
- try
3 D! W: D! k2 ], y# S& ` - { _; p) g; s2 q/ n- l7 }; h6 ?
- #region 关闭Socket处理,删除连接池8 N# y3 F8 {$ k& P
- if (socket.State != WebSocketState.Open)//连接关闭
r1 e! z6 _- R; n6 B# X0 G X - {
/ r1 b% B) b1 B* x& k - if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
$ m2 }& U# o& v" P6 c. j - break;/ L! M( y5 a; K$ u" i
- }
) x# Y. ^" }2 H - #endregion
! {# z" P4 N3 Y0 T7 P( p3 }% T# I
4 o. d [( ^# H( z- string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
, o. }" x+ B* a* ]- c - string[] msgList = userMsg.Split('|');7 R7 V1 g. S) C! c
- if (msgList.Length == 2); v M# t$ U% K8 t9 S" H
- {5 R# \( d3 f3 o0 G n
- if (msgList[0].Trim().Length > 0)
) W$ `" X. s. B7 \* V4 }8 n- M - descUser = msgList[0].Trim();//记录消息目的用户
8 C2 r, \3 [ }' u$ p& v. r - buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
4 M# u) M3 k) t3 E8 A" j0 s3 h - }
: Z3 V7 u* e0 g5 V3 r - else7 j+ Q* P) b4 U& X4 D* N0 m6 |; A* l
- buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));0 F+ M Z) a5 {' j& ]+ s1 f3 i7 O
- ( w1 T( N5 o' j% e, `" l
- if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线. H9 B- @" ^6 p$ S% W
- {
5 [9 Y7 n) v7 B- `8 z5 e& f - WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端1 y- _6 C5 |" i+ ?; n! `3 W7 }
- if (destSocket != null && destSocket.State == WebSocketState.Open)9 @0 ~; k( @ y N5 d. u& P4 t
- await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
! E/ F; ^9 V8 T& {) U/ @/ { - }1 m6 p: q" s8 b; k: C1 p- P* Z/ ^
- else! T% J8 m# A* R' r& }" N# h2 z
- {
/ H" r2 I1 M; D/ O/ W8 q6 Q - Task.Run(() =>
/ u3 {' U. H$ h Y: g0 @0 v. V# P - {+ J) r6 d+ r, @% y
- if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中$ F# b8 Q. {4 p% Y% O
- MESSAGE_POOL.Add(descUser, new List<MessageInfo>());5 u- n1 n: O% i/ G/ W1 H! d: \
- MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息 e! y& {" `: b+ ^8 w
- });% P: U! Z, {3 p* E+ P) n! X
- }
( A0 f v0 x8 H2 \ - }
/ E5 L0 l! f. d# |- J) T1 S0 ~* q - catch (Exception exs)
$ y& g* m" B' U# | t+ m - {
0 |2 J( x$ A6 Z: a - //消息转发异常处理,本次消息忽略 继续监听接下来的消息: ^$ |0 [+ T% O; L+ ? `
- }
/ y! @& U6 C2 k ]) o - #endregion2 y7 B0 M! u6 J# s1 P' D! {
- }0 m X* J5 j/ V& I1 W
- else2 c# N# C- a. ^6 t+ x- P
- {2 R6 @: ?- n g
- break;' ]$ |3 w/ C' a% n
- }. n1 C6 @5 C: M! Q1 m. u1 f
- }//while end
0 [& X/ {# A& \( R - }; h5 h! l1 w4 ^+ f+ j, Y0 ?/ f
- catch (Exception ex)8 Z! K j3 n6 E) l
- {
9 f9 K! h$ s9 F - //整体异常处理
8 i6 @/ Z( ~% D% d2 x) G5 ?* \ - if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
% r2 z$ ~" L; n* _: k, _) ^ - }
! E) z9 C' L6 R; G j - }
4 R# W! c9 \+ T J4 d* k
@3 H% W! Q6 b* J0 A5 M
( I! P1 }1 Y! K- public bool IsReusable
) M- H. ~4 V% y - {* ]% ? |+ I$ R! G" n! S; |$ O$ n, ~
- get
+ x+ t2 y, |/ x$ z6 m" X3 A1 |0 a - {
' d2 k# z6 x) I - return false;, [4 m- q9 m1 W; T2 a4 U4 g
- }' V- r2 ]. F/ a, u
- }2 ^! ^& k2 H5 |6 e
- }
% ~8 x) W$ z3 n2 Z - }
复制代码4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上 点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径 : d9 G Y: X+ Y; D; k. h; o
|