服务器端代码编写 1.新建一个ASP.net Web MVC5项目 $ c2 ~" j# d, s- `
2.新建一个“一般处理程序” 3.Handler1.ashx代码如下: - using System;. W5 \+ X, s4 t* y0 {* K; o& {
- using System.Collections.Generic;
& F1 K3 ?2 }) `: _) x - using System.Linq;
% _7 p' v9 a; l" E! y% }0 E0 g - using System.Net.WebSockets; c; H) A2 G4 S( S e1 J& i1 s: e
- using System.Text;7 k' N0 A4 D. r9 u% ^8 S1 ^) a
- using System.Threading;
* A# F* d; [9 M( ^+ ~1 V- x+ G - using System.Threading.Tasks;
9 ]( X4 V. ?8 i3 M& M - using System.Web;
# w p! Z. V' ]& o8 w8 ]: Q - using System.Web.WebSockets;9 n( U* R+ c: y$ |/ b6 w
+ A! p) X8 V0 J8 b7 D4 T* `
5 r: S3 {4 h4 y4 v- namespace WebApplicationWebsocketHandler' ?2 n$ v0 F; S0 j# V6 W
- {
, ~/ {; m7 e6 C$ m F - /// <summary>/ T, h( c7 d& e; @4 [1 _
- /// 离线消息
2 g% ~# R3 W* \% u& `% r - /// </summary>
/ f6 z8 ]# M" ^ - public class MessageInfo
; k$ {6 h0 b6 g8 J - {" y1 z+ ~, P* p
- public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
9 l8 h( m5 t' s$ @ - {( M4 X Z. N. ^3 g
- MsgTime = _MsgTime;
2 g8 m8 M; O; B: E3 x3 s - MsgContent = _MsgContent;
3 L! k3 U. F2 u& ]/ g" p1 D8 s& ` - }
8 C; }: u4 Y/ Z' I" x - public DateTime MsgTime { get; set; }
3 h1 t- k. Q9 Z& ~9 O" Q - public ArraySegment<byte> MsgContent { get; set; }
: Z1 y9 y. Y- C' T - }
2 b' O% E3 Z7 C/ P4 q( J. o
. w% W5 w" f! b6 G0 Q/ x' [
6 ]& \) R- k q- 8 q% L/ g; R. @8 N, p
2 b: z8 j4 Q* i2 ]3 N. d- /// <summary>
5 v7 |0 r+ |2 t# a9 l. C5 X g - /// Handler1 的摘要说明
' ]/ u* W; S' \: i) h @ - /// </summary>' j/ u, l( l& H. H6 j3 v. E
- public class Handler1 : IHttpHandler' p, R7 Y2 k2 _1 T8 u% J' d$ n
- {( g/ t" ?' a6 j4 ]9 _
- private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池4 x4 k5 e! x, u( t
- private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
$ m+ {( V' R" |; I; H# I - public void ProcessRequest(HttpContext context)6 W% z+ N$ P/ d+ N$ c' m' z
- {
* r4 N' l/ y8 y* [ - //context.Response.ContentType = "text/plain";
4 x. N/ y% g0 E4 r- S2 ~ - //context.Response.Write("Hello World");
. ~5 d1 r9 Z2 H' p; B y8 P - if (context.IsWebSocketRequest)
, E) u1 d" e% `5 w; ^' Z - {
/ h9 z$ V- Z7 S0 _1 x - context.AcceptWebSocketRequest(ProcessChat);9 ?/ T1 z; J |4 u6 x3 d5 u, c/ r
- } 3 y# Y8 o ?! ^) b% }3 A5 b
- }5 h# G/ ~ M! _+ H3 w
& O2 | M/ ~$ }3 y, X+ c- private async Task ProcessChat(AspNetWebSocketContext context) }. b/ R& b; P2 \* I5 \
- {
" H- U( k# y' T6 W; s - WebSocket socket = context.WebSocket;
* r: l8 A1 F5 G z* G/ D6 L* K - string user = context.QueryString["user"].ToString();
' A6 B& u% `2 ?
; O7 t3 r2 O2 X1 D7 M- try8 ?+ \, p$ X& t T- h
- {: z+ y- l7 s( V0 F/ }: u" e
- #region 用户添加连接池: D( h+ n7 \8 {% Z
- //第一次open时,添加到连接池中% L( N4 ^; |! P/ D% h
- if (!CONNECT_POOL.ContainsKey(user))0 B# o0 t" S9 N7 C# l
- CONNECT_POOL.Add(user, socket);//不存在,添加
' v# G3 u$ D1 d9 Z& S, A7 m; c3 g - else
! y3 L0 P. H: v6 _2 K) D' \/ D - if (socket != CONNECT_POOL[user])//当前对象不一致,更新
' P" Q: {0 I7 y: M4 a( c2 T - CONNECT_POOL[user] = socket;
, M! P% c+ e+ n9 G& w; e - #endregion
7 V. a/ B5 Q, s
F) ~6 c( v4 p+ E/ h( @- #region 离线消息处理
4 y% F. k4 p! }) r, D- R- r2 e - if (MESSAGE_POOL.ContainsKey(user))4 O1 ~! `+ w& \! m2 W. U) J% \
- {
i# w+ i7 o3 t9 O, j: h - List<MessageInfo> msgs = MESSAGE_POOL[user];
G( }3 Y$ E, R/ _, h - foreach (MessageInfo item in msgs); b8 L) P6 ], e7 o2 j4 ?4 E8 o
- {/ o% N+ |2 u8 N+ E1 Q0 u
- await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
! Y0 Z- i+ K/ p+ `$ ]4 r0 T/ d% c: X - }2 o( E* o" C- i1 b @+ t( W X
- MESSAGE_POOL.Remove(user);//移除离线消息
( q' ]9 h- w0 G ]6 [$ K& d - }
9 R; g& E" T! `" [ - #endregion
! f. N. e' l4 }. {8 |2 z8 ^ - $ b5 S' Y! \! c$ M* P
- string descUser = string.Empty;//目的用户9 V- v3 E& m$ P ?8 q+ a: k* w
- while (true)
' V$ \/ C4 d6 h% v* f! c/ }5 J - {. \4 X+ A0 m( h
- if (socket.State == WebSocketState.Open)
, B+ J5 W7 V9 I - {
. u5 A! v4 P3 l - ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
4 S7 @" s1 R% |$ [/ A' K5 x8 U - WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
6 S2 i- B5 i1 T( _/ |3 [5 s
A& H; I8 v% n5 [+ A2 i- #region 消息处理(字符截取、消息转发). f. w b0 ` }! d* l& b: p
- try5 b0 V4 H6 O* z& v# m
- {5 J$ y, b3 y2 I) Z" W
- #region 关闭Socket处理,删除连接池2 V+ G/ \. _) _, f
- if (socket.State != WebSocketState.Open)//连接关闭2 a3 E/ r$ \/ o: I" z
- {
2 |5 ]& p k+ |% [3 i' { - if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
. M. Z: w4 f5 f6 T8 Y7 {9 B - break;" F: s/ k/ G; i/ [3 S$ Y, i! G
- }
+ B$ R+ V3 a7 B% O r' |# u7 H - #endregion( ~: H7 z( [* S
- " M( H e8 A& u( k' L3 P
- string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
/ S; U, a' _. n& u7 W - string[] msgList = userMsg.Split('|');5 S& i& G% C+ D( |/ m" [1 i+ q
- if (msgList.Length == 2)
4 g A, }& i. _ - {* p- A" l7 C K: A5 [ H- {
- if (msgList[0].Trim().Length > 0)
) F- [) i) c5 H. ^; ?1 ~ - descUser = msgList[0].Trim();//记录消息目的用户* j$ h) S$ W/ a0 A% F4 i
- buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));, C! O+ [% B2 v" c- g
- }
7 n S- {4 J* b6 t- ?, n7 [ - else
1 z; z9 g, T+ a( y7 n% F' @ ~" w" s2 F - buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));0 d: {; z, ~1 `+ {# W. D2 J/ ^ M# f
; ?* K: A9 q5 D- o) _& y- if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线$ ~0 p9 Q6 p8 G x9 T3 j6 ?/ ^
- {
" b5 ^ p( ^' c! B - WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
; B1 ]9 O- d6 h, |* ` - if (destSocket != null && destSocket.State == WebSocketState.Open)
. v/ T% u4 u$ t% F1 }4 K - await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);8 D, c8 ?1 N6 i* s0 l8 ^: B/ ]
- }6 L6 Z" [& c) z0 K- a9 p0 ]
- else/ \" Z( n. X1 p
- {& B1 D4 Y7 a4 r' z- f* o8 {3 }
- Task.Run(() =>
$ r' ~3 t* h1 r5 g - {4 s5 b5 O& n0 g6 J
- if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中, r$ A! l0 _0 x5 h$ a) \# v! u6 h
- MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
, A( g3 h2 N& [5 g - MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息/ C" o; N. A B2 i0 J' i- E
- });
6 f# Y# b+ h% E( X& y2 a - }7 P) i$ ?) J3 {
- }; b" H, G& g" s
- catch (Exception exs)) P+ d. I. V! S @8 f
- {3 I4 B# C; k7 Y- ?. m+ a
- //消息转发异常处理,本次消息忽略 继续监听接下来的消息
7 w$ o$ H5 l k9 X' A8 t$ p! x - }' s5 X) x* T0 v" c( m3 m T1 h
- #endregion
+ X# D3 p; d! Z# Q - }
( }' E& Z7 H7 i3 W - else& M6 S+ y" q# D. ?: Y L7 [
- {
( i6 ]& [; d$ S1 ^ - break;
+ Q& P" O! ^/ I& ~! S J - }
7 O, u& n5 C# b9 H/ w4 H+ A1 _ - }//while end% H7 m# N: E C( {; D
- }
& o2 f6 U6 i& Q0 l - catch (Exception ex)0 h4 N. E, ?, n7 d9 ^" l7 K
- {, ^) w* r+ W) e/ {
- //整体异常处理" f3 p. l/ k- }6 i) [: \
- if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);+ E- m7 X% |/ `- X: ~
- }7 [$ I5 k. W7 |: s+ [6 I0 Q
- }0 ]0 x5 v* D7 k* b) i* J
. l# g0 C: A) w1 l2 \' |: r; i
0 W$ |9 ~- G) R7 p; j$ |$ q- public bool IsReusable% ^. g9 `, @6 N4 t# J8 V! l! q
- {
* v+ V8 j# J3 O L# R: r" Y2 O6 A - get& j! m' r+ x+ r: {
- {
& g/ T, g6 t, z8 L" `& f" w% r+ o2 W - return false;
1 G( D7 z! A/ o! e2 i( ` - }* o* A$ U/ C* a1 \+ O) G4 N
- }, r: W. q9 a) m( H6 Y/ K5 B/ a
- }0 B/ N9 H/ b' D; h# W, H6 k4 y
- }
复制代码4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上 点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径 {) y7 r- I" E8 U, _ n! U
|