|
服务器端代码编写 1.新建一个ASP.net Web MVC5项目
/ [8 O# L* B- V( z0 z" i2.新建一个“一般处理程序” 3.Handler1.ashx代码如下: - using System;& x* T4 N$ r' _' b
- using System.Collections.Generic;
0 ~! U6 e: x/ t3 \7 h% R9 P - using System.Linq;
- X& v' K' E( ~5 q- z3 S - using System.Net.WebSockets;0 Z- f$ M' @, g; h- q
- using System.Text;
8 a) K+ B% t: ~! p9 {3 O: z& B2 { - using System.Threading;
9 r2 W4 K7 h g! a: ^" v$ M - using System.Threading.Tasks;; g5 ?/ `" n/ T0 V; S7 r8 \ o/ o! M
- using System.Web;
0 Y+ V F- ^, F - using System.Web.WebSockets;* ~& o6 ?+ J ~2 C
; n# L) ^, ]# h7 P- F5 V8 |
: H! P/ n7 Y9 [$ z- namespace WebApplicationWebsocketHandler Z* X8 z N& `- x+ ]' U
- {
/ Y: B% `1 X% X2 Q1 A: H1 d/ ~ - /// <summary>; X! l: A+ D3 U( n
- /// 离线消息
c& w b6 ^" ]0 T - /// </summary>
: }6 l4 ?- q; o: w' O1 `% R - public class MessageInfo1 ?8 s: u% c4 `) y {6 C: g7 [
- {9 X4 I' e, ]8 S# l- [ x) I
- public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)2 R, L. a, } E0 b7 o
- {
* Y* ?8 c9 C( @9 d' ^ - MsgTime = _MsgTime;
! W. m. X; @) O+ s - MsgContent = _MsgContent;
9 @( F) j7 D; @; v& E: Y - }
3 `) x/ d4 I n6 R' z - public DateTime MsgTime { get; set; }3 Q- ]& _( P$ p$ r. K# A
- public ArraySegment<byte> MsgContent { get; set; }* ]( g/ q. F* L6 f% W- k
- }
& k0 [* J1 i8 N' c8 ?2 p - ' n7 S7 U0 I& `/ y* g* W
: z( ^3 o2 c7 X+ P$ y' f t9 {
) I5 M! B. d0 h: ^( E
G2 r, k# J2 i/ K% q; T- /// <summary>
, f1 ]9 d. k/ I$ g! m- ~& f - /// Handler1 的摘要说明& X" i# L' r% n9 c+ f
- /// </summary>6 ^2 {% T9 `7 R+ F
- public class Handler1 : IHttpHandler/ v* W6 x M4 {4 h: r8 t
- {6 ]5 ~: I# X/ I( W$ k. X8 Z+ x4 T
- private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池/ [. F# @2 t; h" f
- private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池3 u9 M# ^. y# I: w; C4 k5 a- a5 f
- public void ProcessRequest(HttpContext context)
- z0 M2 B# n3 A; T: J- t Y/ A* a2 l - {
5 f/ H, _ Z& }. [ - //context.Response.ContentType = "text/plain";
r4 ~. o& ~* t5 E- V0 e - //context.Response.Write("Hello World");$ ?$ k9 ?% q; v, O
- if (context.IsWebSocketRequest)5 n" L2 w2 O U4 a" T
- {9 T! Z1 s/ a' O) Q
- context.AcceptWebSocketRequest(ProcessChat);
) K: w1 ^, {; s, j) j+ p8 W: i - } * f8 u# ~( o4 T6 U4 o) S) d
- }
5 c- U0 a$ v- t h5 c7 Q! Y- W8 ? - * h( | q! t' ~2 h( w8 m* ~
- private async Task ProcessChat(AspNetWebSocketContext context)" }; o8 R9 l/ g1 _6 q( o
- {
- x: e0 o7 J% ]; j+ j2 m) ]/ J - WebSocket socket = context.WebSocket;/ Z& F: ]" a' D
- string user = context.QueryString["user"].ToString();
: L5 Y- e A* [0 Y
. i/ t! b( Y l7 z- try
' k& U( ]% R8 e1 u% ` [: _+ l4 l2 M - {/ l% M3 M z, R, y
- #region 用户添加连接池* S! }$ n! I( r
- //第一次open时,添加到连接池中/ f' e. p& ]5 L+ H, K2 a& ^3 W' l
- if (!CONNECT_POOL.ContainsKey(user))
* r6 r$ L, j, ~. Z- z- n - CONNECT_POOL.Add(user, socket);//不存在,添加
+ A1 |6 g- u3 p4 f - else
) k3 Z) V+ n; t - if (socket != CONNECT_POOL[user])//当前对象不一致,更新
( r3 U9 x6 \, f1 b3 n6 H5 ~5 M - CONNECT_POOL[user] = socket;
8 A; }1 z! D& S4 l* T8 I* e! L - #endregion
6 S, l: L" R) t& Q- h - 3 Y n# x* [- J' R n3 C/ P
- #region 离线消息处理
$ `) [- p' _4 Z6 C3 W - if (MESSAGE_POOL.ContainsKey(user)), {+ j* p( T M; [5 c+ Z( [: `
- {
5 s K8 j9 w' W2 F S" l - List<MessageInfo> msgs = MESSAGE_POOL[user];
0 U0 o+ f8 W, s2 R - foreach (MessageInfo item in msgs)
/ H7 x8 O3 K u, z - {6 v( W5 F& ]6 i+ q
- await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);/ e) X" L t% E/ n, G! S
- }3 Z S$ C& _# n; k5 S
- MESSAGE_POOL.Remove(user);//移除离线消息) ?) _ @/ C; T
- }
" ^+ O( S) R7 u - #endregion+ T6 r1 f0 b. v0 z6 b' h- ~1 K# ~
- u, r4 S3 D. e6 X, @( K! x* t9 A- string descUser = string.Empty;//目的用户
( M, F+ R7 w) E - while (true)
! `0 E: Q9 k9 J$ Y! a+ d0 t( C, I S - {
# Y7 _( ^7 g1 c/ a3 O' X6 ? - if (socket.State == WebSocketState.Open)
& `$ e; s5 Y0 K1 Q4 | - {
4 b; ]% P" [$ s4 K& x# B- k+ q# P - ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);) l1 j; m/ c6 H! Y/ p
- WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);( [ q1 l. E' a7 Y7 k0 A7 o" `
- 5 ^9 R5 B" O; l# ^/ ~* K
- #region 消息处理(字符截取、消息转发)% g+ f. j3 H9 M( H9 X5 W" B4 U
- try
b# [* l, n0 E9 o3 E - {- k0 A3 i9 d. i0 I. g6 A2 o, B
- #region 关闭Socket处理,删除连接池
6 G# B& Y2 p+ |3 N" h D3 s - if (socket.State != WebSocketState.Open)//连接关闭
+ U4 T+ c9 R2 O% S1 E - {0 W0 {3 g6 W! p+ ? C
- if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
o5 W/ z: |) U' L9 J, I5 G7 ^" h - break;! n2 o" Q6 U! H- O9 X
- }
6 g2 Z& M$ M9 C/ a7 n- o, }. B - #endregion
" x1 t" \% L& |6 L1 q: f1 m - ) H# m5 f; b' v8 W0 T
- string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息$ ^) g0 i; F; G# S
- string[] msgList = userMsg.Split('|');
4 I' v1 w% ?: N/ Y+ L - if (msgList.Length == 2)4 a7 m- ]- G$ i* ~, C6 W
- {
% b1 k7 V0 M, }4 F9 i+ p - if (msgList[0].Trim().Length > 0)
* p7 V- R8 x$ A# u - descUser = msgList[0].Trim();//记录消息目的用户5 s" d7 B9 \. a5 h1 {
- buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
6 H9 X3 x- s. c4 k - }
" o3 L \ h0 U. u% @! J - else5 o/ J5 R. l) H- ^% T5 [! b
- buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg)); t" u7 P0 n3 f# I) n+ B% Y
V9 b3 P; R' C% j! A; r6 s; q* N- if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线6 V# L5 e) M _! N- c( N' M9 H9 J: S, ~4 t
- {
6 I7 e" c( Y7 _$ e, f - WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
4 s' L) c' ~5 E' U% {/ }% @* p h - if (destSocket != null && destSocket.State == WebSocketState.Open)/ M. G. j5 N0 g3 a( `
- await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);' a" H# [6 i; ?2 O0 L/ j$ S
- }8 Q$ ?" l9 v" \% Y3 R5 [+ k
- else
, @3 R1 G- z2 c& }' v; j, j4 Y - {
5 V: |& [8 f/ ~: [+ V - Task.Run(() =>
1 _$ u# G! N, l& P6 D1 L - {, a8 C8 T, @- D% K$ N
- if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中, L3 N. ^6 t0 c, B! k5 |0 x9 o
- MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
3 Z' ]. B+ C2 w- V+ B - MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息, o7 a. m9 M: h6 |/ K
- });
0 D$ X2 G( t! ?0 V1 k( k& d% } - }
0 Z, ~& H6 v2 g3 `" `- n+ d# m9 l - }( A' R N! Q$ ]4 P/ k
- catch (Exception exs)
' r. n1 O9 m3 d. }6 } - {
$ M, |" \- ~1 ?9 N' w% R - //消息转发异常处理,本次消息忽略 继续监听接下来的消息
: V8 r& f2 d* K7 G R1 b - }
- ?/ F! t0 T# { - #endregion8 ~' d, @3 N* s0 s
- }
+ o: P4 C) Q! n$ _* R3 t- c( t - else
! D3 P) N- j( n - {
! u% e" M6 {( {4 c) b - break;4 W+ h8 K# b* h$ i9 w1 t
- }
1 G! L- j: u. Z/ Z9 @ - }//while end
$ c: i7 ~+ w" e% D1 H) A - }1 S( j# e7 ` ` I
- catch (Exception ex)
7 @$ F! X0 d- [ - {
. E# n1 B: h$ [: i2 X - //整体异常处理, P; |8 H# H1 K3 E' I) p+ @
- if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);+ a, {' {4 N8 Z6 r
- }
: d' i6 ~& O& n4 d5 Y - }
8 s# s. @' \* X. T+ ^- E - / u$ P, T; l6 s* N' z1 R! H# j
3 t4 c1 |, `* h% g- public bool IsReusable
4 `* G8 L2 p) _1 R2 ] - {
9 Y/ }- Q- W8 S% C N1 s5 } - get
- K+ q% D1 j: l; M - {, {5 q2 Q2 z" B* n1 `
- return false;% v1 d" y+ p& ^ N3 w- P* t2 |7 W
- }
; Z/ O* v5 `% f- C' O - }
" ]0 J' w" e5 d - }
! N9 [- ^: I# ^% q; x, {' \' G; }7 c - }
复制代码4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上 点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径 $ L: u7 l) S" r1 Z6 c H
|