服务器端代码编写 1.新建一个ASP.net Web MVC5项目
7 C1 K2 Y0 z) A/ M7 L- C$ p2.新建一个“一般处理程序” 3.Handler1.ashx代码如下: - using System;8 ^6 [$ c" U9 O8 C0 A$ Y1 r
- using System.Collections.Generic;( u$ d) C8 E* G5 b
- using System.Linq;
9 k W: ~. o. R( |1 f5 h4 c. g - using System.Net.WebSockets;
% Y5 `1 I& B7 }& ^1 j- K& m - using System.Text;
0 n5 ^; S% m6 v9 |; _! y - using System.Threading;. ~9 k0 Z7 Z6 x6 t6 x
- using System.Threading.Tasks;
/ o1 c( I% J& B/ w - using System.Web;% @8 y" R8 G% n+ J- z
- using System.Web.WebSockets;. r* e; t- ~: U0 R
6 _" S) u( U$ O- , k$ D" X! P9 V
- namespace WebApplicationWebsocketHandler
, V5 u: m1 R: D5 x9 ~- ? - {6 ~- m( z& N6 h- ~+ S. R9 k* \" U* ~
- /// <summary>
! v0 `! s& f% g6 c - /// 离线消息) s. J* z. q. Q7 T
- /// </summary> i6 ?1 t! j3 n% k' r1 b
- public class MessageInfo
4 X Q* k& C$ N9 |) V3 d7 b - {
- H4 ]1 V1 v: p% U- r - public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)1 c& c' \0 x% T2 q9 U- ]' ]
- {
' o3 j' M. w2 V* {& E1 b; W - MsgTime = _MsgTime;
- ?/ @* h0 p- Y3 e$ B+ l - MsgContent = _MsgContent;: S' [6 H/ _1 g* @( `
- }& \: |$ G/ a4 \/ Q( y
- public DateTime MsgTime { get; set; }
, u) `4 W* ~8 }: G) x1 {& q - public ArraySegment<byte> MsgContent { get; set; }
# f5 h9 a" @% ~) y7 H V# \ - }' ~- e1 D- B8 v, x7 `
- 3 b, A/ x: X: @
- , A) a, H, \( m8 }
- 7 d' }2 e3 i. q0 b
- 0 q' }2 D" C4 V) A
- /// <summary>" t3 \% u0 k( s9 K0 W0 Y
- /// Handler1 的摘要说明
1 K1 `7 {: d, A - /// </summary>
- i+ X5 i2 L0 g - public class Handler1 : IHttpHandler
: A( r: j* k7 J) U: } - {1 O5 g' i9 K! C, X
- private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
) ^; V1 K2 p9 p, W - private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
1 ]5 m5 Z S1 q& L/ x" g" j - public void ProcessRequest(HttpContext context)5 {2 k. X3 Y& r! o% l
- {
$ n/ h* a9 q- Y& n8 [& P - //context.Response.ContentType = "text/plain";
# q0 }) ?$ U7 H& K4 L' L( T - //context.Response.Write("Hello World");
/ o, Y/ j ^, K" Z0 r$ n2 M( H( B - if (context.IsWebSocketRequest)
/ Y" f v4 _3 W1 F! t0 ? - {
) ^2 M/ v7 z# |; O. q0 L - context.AcceptWebSocketRequest(ProcessChat);
% X: c; y' G6 ~; O - }
7 V, k0 f9 O9 q }2 c - }
1 i- }" v* t3 h4 ^ - 1 G W% V) S* o/ p/ {9 k9 u
- private async Task ProcessChat(AspNetWebSocketContext context)# ]8 q2 N0 j) r
- {
0 y& J/ e0 ~' V& W) R6 D - WebSocket socket = context.WebSocket;2 s# T- p& W5 F' D; S' Y
- string user = context.QueryString["user"].ToString();
: C. h' }: G# O0 h - * P+ Y1 }; u/ R& M
- try
W% r8 }" X1 J' S, R, P5 g - {0 j/ h+ h/ y6 r! G' X) p, G8 w
- #region 用户添加连接池
) K5 N- Z4 u: ]; }4 W - //第一次open时,添加到连接池中- M; ~& [: f- s' H8 v. `
- if (!CONNECT_POOL.ContainsKey(user))
0 }% ^; G& K7 @' Q) { - CONNECT_POOL.Add(user, socket);//不存在,添加
1 S1 I# H0 w* S' h( o# a - else& x2 w' M( k3 }: ~5 u" h
- if (socket != CONNECT_POOL[user])//当前对象不一致,更新3 K7 ^5 f& U& `) }1 {, m
- CONNECT_POOL[user] = socket;
& H: m* D3 s& W, J - #endregion
" F! M/ P' O* g - ! T/ z: r7 S, ` X
- #region 离线消息处理9 i2 ?4 m7 ?- P. w' K' _' C
- if (MESSAGE_POOL.ContainsKey(user))
' _$ l- b+ w/ w% V, z2 }* T" d - {
H" @! m4 f* Y z2 f1 j/ ` - List<MessageInfo> msgs = MESSAGE_POOL[user];
. j. i9 p! F5 K; X, q - foreach (MessageInfo item in msgs)& l+ P# w5 m! N, O3 f
- {9 ]4 D) ?4 ~! D- ^4 H
- await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
8 i3 Q% M5 F. k2 b - }
9 U- `6 u& N! J* V/ U - MESSAGE_POOL.Remove(user);//移除离线消息/ S! {8 W; ^, K
- }
4 m( w0 ~8 W+ a# k$ v - #endregion
( L3 f/ y3 B& b9 s - 5 C) J. a8 z5 C+ Y/ A3 Z
- string descUser = string.Empty;//目的用户
* D4 a& C: E4 M Z" d. }/ x - while (true): o p& S) `7 \- l( \8 Y
- {
* N7 d e# n ?0 s* ^7 I - if (socket.State == WebSocketState.Open); Z% Q% v4 l* h, z, m8 D9 K
- {
" y# F* k+ w1 t% L& _% S5 a: U - ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);4 f0 d! t: q9 _: G7 @4 H
- WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);6 x9 L2 M1 H* Z- U& v
- / t1 q$ ]5 M( |2 _
- #region 消息处理(字符截取、消息转发)$ Y' g3 n( e& x) ^+ ^% `, I4 X
- try, X4 c' c$ A0 k/ h( C; P
- {
- ^; e6 J4 [# g7 ` - #region 关闭Socket处理,删除连接池6 o$ X2 {0 l. @
- if (socket.State != WebSocketState.Open)//连接关闭+ C- S$ S- C4 b1 l
- {/ Y+ G& D6 O. j8 ~
- if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池/ C+ j2 q0 y- C$ R$ _, u
- break;
# G' O9 s- I8 Q - }+ k1 ?8 L2 h q
- #endregion2 p, z/ ^1 e6 p) V' Z( v: C
- J& ^1 I8 ^* u& v4 h y9 Q% f2 M) z- string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息 p& V/ c+ ?% G1 ^5 C% ~. e
- string[] msgList = userMsg.Split('|');3 ~' _ x+ N3 J1 o
- if (msgList.Length == 2)
* c- d. v. s5 A. P1 U( a - {
) O+ p% z z* v/ m - if (msgList[0].Trim().Length > 0)3 d; P: E2 k& l7 N
- descUser = msgList[0].Trim();//记录消息目的用户5 z6 F1 |1 h& P- t, g
- buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
$ |& a q. h, p9 c% j1 G! b - }
& w3 K+ `# R! |) X& F, y- w- U - else
( w7 U- r2 s" ` - buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));7 Y9 X1 p1 l! L K! D$ B9 A
P O1 k7 N' S- if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
1 e5 d2 j) q( c - {( q9 v: y( q$ L2 ?' j
- WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端& B$ Q5 x5 |0 l3 V
- if (destSocket != null && destSocket.State == WebSocketState.Open)
- K( ^# h# [5 @& k: a - await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
. i$ ^- O/ w0 ^) K0 G* f - }
. i. J9 ?3 B% z* Y: }6 k - else5 a: k3 O) V' x
- {
6 |1 D5 V9 k: g! k$ I: e - Task.Run(() =>' q ~" J" o, t6 k# k: R% E
- {) h; `+ c; b' Q
- if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中' q' f5 b* x$ f! E8 ^( G
- MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
" t4 r: ^. g- n7 c7 d4 W - MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
/ ~ o1 a" i K" E. u3 l( | - });
( V* r6 t) ~- ]3 A8 y7 S/ ^ - }
0 J% }6 p0 y4 ^* h0 [, J* X! c - }
: g% w5 ]; P( w6 t9 Y! H1 `! V - catch (Exception exs)
5 q+ q( A. @+ c% z1 W - {# _9 J0 H4 H b& L
- //消息转发异常处理,本次消息忽略 继续监听接下来的消息
" ~- `6 Y0 M$ R, U: F& O( D" d+ e- o - }
& @3 l# |7 y; _ a0 Q - #endregion' d& o3 i& ^0 ?4 W" u
- }
4 w& {7 n- V6 a. G - else
: T3 g t: p: e! s; O% H/ G - {
4 x @ g1 D$ [0 m( r" R - break;( v( ?" ^5 q6 C1 I7 A+ Q
- }3 a- O2 [# z4 b' |
- }//while end
1 n' d5 O% s) X - }
J+ C. C% v+ \1 t r% A0 u; Q8 f - catch (Exception ex): _% d0 j, \2 B3 M, o
- {5 M* z5 r0 @2 T. l$ Z
- //整体异常处理
9 h; q0 I% t! Y9 o( X$ n - if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);% l' D1 _ }- {# x
- }
1 R- j- ]) G' D1 ^; e - }. Q a k0 a6 d) F4 v
- ) V4 a1 I' C4 |" i4 N) q$ Q
+ Z- J" i9 S! I @9 x% w- public bool IsReusable! H3 B. D8 M, B% h. L
- {
* v! O" F7 P( d$ `3 n$ R5 L4 E5 V - get, R* m5 |1 @# R0 w+ S( s
- {
O; K v! b! j" t- \# k8 ` - return false;" m# h" F) l9 P* N3 I4 g
- }
8 m/ C( f# c+ ?$ P2 [7 D' K+ o - }# Z( J$ w# p: p" b6 c7 N
- }* F2 k3 n: f% c# c+ q
- }
复制代码4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上 点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径 / c) V+ |# F7 G
|