|
服务器端代码编写 1.新建一个ASP.net Web MVC5项目
- N& G2 ?' X! O B2.新建一个“一般处理程序” 3.Handler1.ashx代码如下: - using System;
( v9 b' i7 H* l; J! }9 B - using System.Collections.Generic;
( T) I/ p6 C, S X m' ` - using System.Linq;
0 u0 w; |" \# ]/ @7 h# }/ L - using System.Net.WebSockets;
, j2 c8 @; H* n9 T" d - using System.Text;
' e5 t! Q' s2 Z$ D' C - using System.Threading; ~$ L: V3 d9 D* o- L4 l
- using System.Threading.Tasks;' \6 C& ?3 ^ x, c4 P
- using System.Web;
2 M- Q$ _; C. }: ~/ R0 Y - using System.Web.WebSockets;
1 u( f3 X3 Z; K/ v - , b& B8 N2 x( b8 h4 ~) f$ T" y
/ }4 M1 F' o; w2 V( s8 l$ s- namespace WebApplicationWebsocketHandler3 S) V$ G' I5 N \; H- o1 S1 {
- {7 L8 ^% Z4 H" J4 p
- /// <summary>* J7 w8 ?$ r8 K3 L* `2 z, b' F3 U
- /// 离线消息
8 w; U" v/ d) E. U, o/ z. H - /// </summary>
$ V9 n J: f& ?; P& u5 i v - public class MessageInfo, } b; y1 D" M$ J
- {
( ?! X, j/ B6 T - public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)+ }; C6 X, C4 ?6 Y: D/ @8 e4 y& ~
- {- g8 Q) F$ t$ h( f" u
- MsgTime = _MsgTime;7 l" ~( @ Y0 T3 R
- MsgContent = _MsgContent;; n+ k" G; H: f$ b
- }
/ ~& f6 _! k; ] - public DateTime MsgTime { get; set; }
* S, `* R. D/ [1 F/ |4 c( k" k9 Q - public ArraySegment<byte> MsgContent { get; set; }
- d+ \% U$ s( l9 ^' M: A# p0 g. u - }
6 M7 U7 o9 { g0 s' x2 |# w - * o7 c9 x9 _* N. w% E
- ) w1 l' ?* u1 }) T" }; `; P! J
- 7 ?' B- O! x; ]1 r
- * `* X- d* G; f7 H" x
- /// <summary>
5 a1 ]# q, o0 C' G - /// Handler1 的摘要说明0 K0 ^# X* ~ h
- /// </summary>
' V) W: x4 W" O+ x9 N; f4 | - public class Handler1 : IHttpHandler
9 _3 J6 F2 `1 v9 Y' | - {- P! q1 ?6 `3 \9 V7 I# E+ l
- private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
2 i6 l& v0 u8 {8 A - private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池( ?! L' e- x7 ]; ]6 n$ n
- public void ProcessRequest(HttpContext context)' q, k7 n% F9 f7 U8 x: U
- {- a7 y! X8 ?4 b, l6 D$ X( c
- //context.Response.ContentType = "text/plain";% \! E. w: w; i
- //context.Response.Write("Hello World");
4 w( N4 P+ {$ s) h - if (context.IsWebSocketRequest)3 |- H7 T! l; @; g& F% ~# P
- {
% A4 n5 p/ g- R2 E" Z( O( t3 F- B# Z - context.AcceptWebSocketRequest(ProcessChat);
, o: U4 u* F0 c' b: w- ^2 ?( U - }
^0 K% v5 o% S3 z. V/ J - }
. `% }. S# q+ ]9 Y/ g* E
# h) S7 K( U# m( E* u# W2 L; E- private async Task ProcessChat(AspNetWebSocketContext context)/ O* ^0 R- v# C$ t, m- Y7 z
- {
5 E7 l6 Y$ A4 i, [3 j: F1 W - WebSocket socket = context.WebSocket;
. s% D2 y* d) O* b$ l$ i& V - string user = context.QueryString["user"].ToString();
& {' I0 m4 Y; L$ X6 ^, ~ - 4 w4 M+ u" I5 ]0 S- o a( v
- try& J4 T: N" [2 m! N
- {
2 k# j, ]( l+ p$ @6 D0 @ - #region 用户添加连接池! u! r5 e* A) S2 U5 u
- //第一次open时,添加到连接池中
4 h* I6 W; g0 H/ h0 H - if (!CONNECT_POOL.ContainsKey(user))
9 W, ]9 G$ ]8 o# C) S1 o U* G8 @ - CONNECT_POOL.Add(user, socket);//不存在,添加5 a, C) j. p4 h9 x& C6 U7 w4 J. t
- else
2 _$ Q- X _. N' R0 S b - if (socket != CONNECT_POOL[user])//当前对象不一致,更新
% y( Y q! ~, P* ~1 l: U - CONNECT_POOL[user] = socket;8 w2 e; n {3 Y7 W, s3 q6 i
- #endregion
* x+ ~" J: x8 L1 q5 Y3 z% O
# f- w3 E" }& k9 L) j; D- #region 离线消息处理% Y# P# F" F* Z
- if (MESSAGE_POOL.ContainsKey(user))( ]/ F# G: h6 o# }/ V
- {+ L* \( j' A8 w/ e* N
- List<MessageInfo> msgs = MESSAGE_POOL[user];
# \; A3 X. L0 z8 e" T) M - foreach (MessageInfo item in msgs)& c9 A2 z9 M, U2 f+ \- T
- {+ U u$ T1 w7 ~$ j5 K
- await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None); v: a; o, S) i- [; b! A
- }
1 P5 z4 E, c4 T. J) g( ^ - MESSAGE_POOL.Remove(user);//移除离线消息
( @4 ^8 H' i4 y/ `, L - }
: e! i4 Z5 k5 n1 _$ O3 x - #endregion' \0 \* n# D L! J( Q
# }. b% Q6 B" {+ q8 U- string descUser = string.Empty;//目的用户* B8 J# {% Y' Z# O/ d9 @- [! _
- while (true)
; _. M" e3 V* z$ {2 N8 s! J4 f9 \ - {+ Q; f! b4 s$ }4 N
- if (socket.State == WebSocketState.Open)
2 t( Z: h4 z( |; Y9 z; Z - {8 k4 p; C0 ^; ?% X, i4 \& k5 h+ L
- ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
6 X) b7 d T& v! N$ c5 T2 [' X - WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
9 d: s/ {: Q2 N( L( a3 J- e! j - ! V0 Y: x5 g7 h' S
- #region 消息处理(字符截取、消息转发)# N3 Y4 M0 s& U. d
- try$ Y0 R# U9 t; H2 o
- {
' T1 L$ d1 ]0 w& {) z& d0 j - #region 关闭Socket处理,删除连接池$ b- N/ L" [% Q+ c0 e: s2 o
- if (socket.State != WebSocketState.Open)//连接关闭
0 J X/ t$ N: y( T; Q7 }! e7 J0 V - {- j: c; d# }5 E
- if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池$ a; ]5 j* m/ h/ I- c- \3 D0 M% N
- break;0 ]7 U% I- {4 u j m* U! F
- }
) u T6 [+ A4 B" [" L - #endregion
$ f. G8 U o; M5 S& q9 t
/ K, X( ^/ {7 O; I5 }" M- string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
, M) l' T! r7 `. @! }9 P% W) ]% H - string[] msgList = userMsg.Split('|');
% D4 X( N8 \8 D - if (msgList.Length == 2)
" } h& u! B k I" c8 ^- r - {
- i- `( R) y- @. ^( d7 ]' Q - if (msgList[0].Trim().Length > 0)
" e7 s b9 h( p7 j. B- R+ B - descUser = msgList[0].Trim();//记录消息目的用户5 `& c. V( E* u, O& u* q
- buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
4 O- r9 D8 F I' w: B k3 K5 ]% C - }
7 X8 u, @0 Z/ {0 ^ - else7 v) f: M! D$ g& [$ R
- buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));8 x% j" y ~! V2 ]5 N! J
- / W9 b' s& p8 S& Q) h0 a; N% i! G
- if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
7 ?) p) ]& [& d. l3 V - {
$ A" F1 ]4 }9 G2 ^4 T: {0 Q - WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端& O: N( g' o5 Q! R; k' k
- if (destSocket != null && destSocket.State == WebSocketState.Open)% Y. U3 K% Y9 U8 l1 t1 v* Q8 Q# u
- await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);- E$ I8 B( N* v; C, S. Y& Z ^$ t* Y
- }
5 Y1 Y# c" I& C$ l7 i - else
+ m7 ^& s! P2 C5 s$ i+ z - {5 v6 C8 M+ u9 ]" D6 m
- Task.Run(() =>
! ~2 m1 h1 R( @ - {
( f0 t1 w1 ]) O! P1 k - if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中, B `, }7 }# T4 B+ c, J
- MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
) t: z* m8 Z# a8 n* `4 ` - MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息" q& Q5 K. x6 ~0 S* C
- });
0 U" {1 d4 q/ Z - }
- T$ n @5 N' h8 f, x3 @ - }$ d' j' e3 S* K6 s
- catch (Exception exs)# K. a6 m# n$ l) B' G
- {
$ f0 f6 z' L4 c& G4 D( R6 t; C - //消息转发异常处理,本次消息忽略 继续监听接下来的消息; a& w, K5 ~6 ]; R
- }& L$ ]% w. N d8 \% A f7 [( R
- #endregion
( r( V& ?8 L& m9 {; I, e8 { - }4 _" u4 Q+ @0 s$ X2 F$ N7 ?
- else' _/ A1 U1 ^4 Q( x& e
- {
- w" _8 \& Y0 ?3 T/ r - break;0 f3 o! v, ?+ U0 S8 s) g
- }
, Z( z) Q3 d- c' n d) G+ E - }//while end; p: [3 L' a, f k3 O- P* K$ B) z
- }& y# D7 V( @( r. q
- catch (Exception ex)
+ }( N$ f+ V2 M7 r- k - {
5 z6 l; ]5 P2 e - //整体异常处理
7 u2 s9 R! w* A* ]. _ - if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);- k+ v% k$ ~. X3 o2 ^* c/ W
- }0 @$ a% z% W2 R7 ]8 y. R: {# K" K
- }6 l! d7 I) R% b5 ~
- ) i6 m2 `( ]+ }+ B2 E" {8 {7 y
- ( W+ M/ y$ o8 F$ I* ~
- public bool IsReusable, u. b( ?% b( l# ^0 v* a- J
- {
# r1 O! N B7 w6 x) ^& v7 F - get
& B4 x5 a8 `4 h; X b s$ C - {; J2 ^8 T: ~+ V4 [5 _
- return false;
0 d; Q6 d" j0 O7 v; ? - }
7 s# ` B R/ W* D0 x - }6 {# V3 d2 f5 j" y- z( i1 u
- }; q: _# l: ]$ u# f
- }
复制代码4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上 点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径 $ S* d4 ^) L f' `; m
|