|
服务器端代码编写 1.新建一个ASP.net Web MVC5项目 : x% W0 F6 ~$ C
2.新建一个“一般处理程序” 3.Handler1.ashx代码如下: - using System;
N# I) V! N: V; D - using System.Collections.Generic;2 b7 j& |6 P8 ]6 O' S4 D0 n& t
- using System.Linq;
7 B* k5 W; X2 ~3 M2 h [ - using System.Net.WebSockets;
0 Y# J5 q" T4 h - using System.Text;
! _. }5 ^. e: u - using System.Threading;
% |5 P3 Y* q! {1 g; e4 ?* z - using System.Threading.Tasks;- q# C' N0 l3 R, M4 b
- using System.Web;
- H2 y4 W- V4 ~" M( W& B3 P - using System.Web.WebSockets;
2 T' a' X6 v+ H" j: m - 5 {5 P9 J: U3 n$ g$ m; ]
& b0 z3 n5 W4 i8 d% _% J- e. c- namespace WebApplicationWebsocketHandler
$ J4 [3 [% u1 Y7 [ - {
9 p! H, K6 ?3 F/ B$ A2 ]3 L - /// <summary>
R9 |6 f+ D% W/ q' @* x - /// 离线消息: O7 b6 r2 U& w- k0 D$ p
- /// </summary>
8 z1 r4 k! B8 J) o; U: W# l9 a% q8 | | h - public class MessageInfo& ~0 f4 n1 i8 p5 \. o
- {
" N( O$ A- P7 b8 F2 W2 ^ - public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
' r' z* o: G( z' { - {
* I/ x! {# y( P - MsgTime = _MsgTime;9 n1 T3 H' D+ u x4 ^# C
- MsgContent = _MsgContent;( C+ K3 f, O/ c0 c0 D }; k0 L. u
- }* G' J: _& U$ h
- public DateTime MsgTime { get; set; }
# A, R( D( W; }) B4 f0 ~/ b" ] - public ArraySegment<byte> MsgContent { get; set; }/ C! o5 Z, I0 i* [3 s" j' E% z
- } B% [1 J! n& h7 S- }9 j) h( F
# P% A) @ o* M2 H+ @
! t) m5 a% K" A, v! y/ t3 K
, b- s% ?, ]' K3 v# H0 Q& X) k- 1 S0 `( G" F. v5 R1 d" g- d0 @
- /// <summary>1 ]. [6 n' T9 M1 Q9 f
- /// Handler1 的摘要说明/ V2 Y- d9 V B5 c7 L G; `+ m
- /// </summary>9 t5 B: i3 z* w, N- t4 ~6 b$ z
- public class Handler1 : IHttpHandler& K. S! p7 [4 F5 s$ M% A) U, d
- {
Y/ c' A8 q* k1 F+ y4 L& ^ - private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
1 g6 f6 O- y9 O! B0 ?' Z0 s - private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池8 i8 A2 S* H* U" e8 y. C2 t4 W5 o
- public void ProcessRequest(HttpContext context)
/ G" p3 q& i: a5 L. B( c7 w - {% o& v% q& C8 \6 Z Z1 v3 s
- //context.Response.ContentType = "text/plain";
' y3 M% d/ r7 M6 q - //context.Response.Write("Hello World");! w5 ^9 ?# t& @5 y! I
- if (context.IsWebSocketRequest)' _2 f( a# d c" K
- {( V2 e5 u3 |9 c0 J1 u! y# Y, j
- context.AcceptWebSocketRequest(ProcessChat);" H# e9 b: ^: D$ Y1 C1 }
- } . B) z7 F X" ^/ E
- }
& c! ~. L' L: f8 K6 \
" a& g# X- e9 I2 C! S- private async Task ProcessChat(AspNetWebSocketContext context)
7 h, C8 H* `# K- d9 _; M - {
! ~3 w) f8 K! _2 ]/ J/ I4 S$ e5 n9 I1 E - WebSocket socket = context.WebSocket;
+ k/ I3 S4 Y: \8 Q1 w! a$ X# V; y - string user = context.QueryString["user"].ToString();
/ I! S1 Z# w$ G# l! e6 Y$ ?
: F1 H/ E# L5 s) ~7 Z- o+ U* O" n- try& l/ O& g/ W' F. C# B: U
- {# ~! D1 i) |; W4 `
- #region 用户添加连接池8 z9 F# S. a. `2 ~: ~1 O4 k, G
- //第一次open时,添加到连接池中
d& F& R" y- @. G9 f$ Y. \1 t4 q3 b - if (!CONNECT_POOL.ContainsKey(user)), h' _& O/ V3 ?% _3 g! B
- CONNECT_POOL.Add(user, socket);//不存在,添加
: w& @. U; t/ [# p% ~ - else! q" r1 P4 B% w! f/ p* J
- if (socket != CONNECT_POOL[user])//当前对象不一致,更新
7 X8 b0 u7 w: h, \' M5 m# {5 m - CONNECT_POOL[user] = socket;0 v( G0 a' z& g1 S6 f) k
- #endregion
3 v. w- l, c) B) d+ o! L3 h
6 m( z$ _3 E5 g2 h+ V- #region 离线消息处理6 |& O. T" V8 q
- if (MESSAGE_POOL.ContainsKey(user))( n& E; }. `5 h* ~ \
- {9 F& |& S3 W$ R8 U) u* A) i
- List<MessageInfo> msgs = MESSAGE_POOL[user];0 T3 l+ k7 f$ D ~" L$ ~
- foreach (MessageInfo item in msgs)6 T; {" v0 i, m) X: I
- {
1 I8 l% F+ Y% L6 @/ c1 [9 E - await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
4 U W" i0 y6 s. k" z - }' D7 m( t& t% }
- MESSAGE_POOL.Remove(user);//移除离线消息" ^( u: f. m5 Y7 p& }4 T
- }; ]8 G' s) l7 y! z
- #endregion9 Y4 ^" U% l( S4 h( U
- 9 c S) ~$ i6 o& L6 B% W: H
- string descUser = string.Empty;//目的用户
1 D; O# B( H& G - while (true)) U3 Z: u" _+ q, x8 Y' o( O
- {* J0 i& Y/ Z6 `; `8 Q
- if (socket.State == WebSocketState.Open)
" c: k2 P0 W- E - {
' G& E+ s7 O& j! H4 W$ z! N - ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);) ~3 d; N+ ?$ H" ~; \
- WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
" z/ ~% @) r) y$ a5 b1 W8 A) j - ' X* f) M6 Z4 a9 M, }7 }7 z
- #region 消息处理(字符截取、消息转发)
3 U& F8 {5 Y4 R" w* `4 _ - try
8 N! a; }, _: N5 X* X4 U: s - {
. x; q9 U; [/ s( [ - #region 关闭Socket处理,删除连接池
# F3 @' a; H v) L* ^ - if (socket.State != WebSocketState.Open)//连接关闭
/ ]3 N) A# F2 R. q7 V# L% P - {
1 N9 X. o. b' b, `: J - if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池! [! ?8 P4 T( v* J+ ] A7 N
- break;
- h9 v+ ?+ X# X0 J1 l$ ` - }( A7 `5 }! g0 l7 f! _/ C
- #endregion
1 t- b+ A& [" w2 C' J
5 ^! k. n7 m4 m- s8 t- string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息/ O! E/ R! B. `! Z1 A. q
- string[] msgList = userMsg.Split('|');9 Q) Z& l `1 p2 y/ I+ V: p- ^/ v& L/ a
- if (msgList.Length == 2) j' Y% H }4 z; w0 V+ b3 `
- {
: x, ?& ^# W4 n+ N9 T; w - if (msgList[0].Trim().Length > 0)# t% J. N" ?8 Z, H' b
- descUser = msgList[0].Trim();//记录消息目的用户0 }4 ], m7 N% O" s/ l4 C
- buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1])); W& Y' P+ `* L- E0 d
- }8 `5 U* g0 q6 z
- else9 _! H2 m1 Z9 `) H! @2 b7 t; p! P
- buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));3 m& u9 t5 I$ J( L! @
# D( ?' O) o6 ]0 T `- if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线( B: P, S9 ^1 |6 V1 ~ p6 d
- {; R" i# C$ j) L7 C' t, G: }7 V
- WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
0 D% g. x/ a+ W* G( r: ` - if (destSocket != null && destSocket.State == WebSocketState.Open)0 a$ P6 h4 A) @. [& w) M% s* k
- await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
% F5 ~( h2 I& T, P$ A. j - }4 `, ~1 z( B/ v) f' [
- else
5 y+ X w& ?0 g6 U* r - {
5 _ I$ {- D b% m! b - Task.Run(() =>- X/ G- f/ O, E# t f V1 _
- {2 ^4 c1 F! x4 |8 [: Z
- if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中0 [, x `3 H* T! R
- MESSAGE_POOL.Add(descUser, new List<MessageInfo>());: K9 n3 x' Z9 T/ ~: g. \3 ~2 W
- MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
* ?0 W: ?% c! V3 I4 q7 i - });# F6 R0 j4 A; I8 y5 V# x+ \7 v6 O
- }
) h5 t+ ]" O7 x/ U1 [& O- Y - }- S% g7 ^. R& T5 L
- catch (Exception exs)
2 m# K5 s* s0 i& I% Z4 V+ D - {+ g# v0 J0 t/ T4 q
- //消息转发异常处理,本次消息忽略 继续监听接下来的消息
1 c& e" Z; Z* [, b0 y, p - }) p% s* S7 Y# C1 e7 X
- #endregion
( {1 Z. g& q* A# Y: ? - }; P1 M/ q- Y' z. ^7 L9 o
- else7 t# p5 g1 t! U6 q _* n
- {7 l1 I+ o f, K# K4 K0 Q+ R
- break;$ c3 e3 o2 C% @2 ]$ `5 ^
- }2 O/ b, Y, V7 E+ r
- }//while end
5 L! @$ E: b L/ w - }
. j* ^6 A3 g! s# E - catch (Exception ex)0 K1 k, \7 _' o: Q) e& W) P
- {
/ W! h. c1 t F) ^* {4 j - //整体异常处理
~& q g8 K; C v9 v6 H+ K" h1 U! e - if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
' ]- O: E# |4 u, a0 R - }' S1 c1 A R. N- V
- }+ r; r6 t# M4 w/ G" a
8 \; I6 t H7 |9 ?2 Q% D
0 z" ?, ^, |) I1 Y6 }+ V/ x- public bool IsReusable
$ `" \+ m: _4 H3 I$ T- P - {
3 _; J7 f) i9 \$ _+ e0 ]3 g - get# f6 M1 L1 _9 R) Y: J N) e
- {
9 a5 q7 L% f! Y- c - return false;
4 f( e5 A# Z# `! C1 }5 K - }) J! K' ~" V! Z7 m& A& x+ w5 Q
- }
; T T' Q3 G/ |9 G! j- z( } - }
! \: t- ?3 E3 O. T% E! U4 t9 g - }
复制代码4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上 点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径 ; j; G8 e1 [" r. f+ H" c
|