您尚未登录,请登录后浏览更多内容! 登录 | 立即注册

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 10795|回复: 0
打印 上一主题 下一主题

[html5] 在IIS上搭建WebSocket服务器(二)

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目

' d" K: M6 o" O  F# I+ z) b
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    & C2 I( V1 m8 ?6 k$ `
  2. using System.Collections.Generic;
    * R; L: D; m* |" I  V
  3. using System.Linq;
      a6 B" ^* t5 B5 \) ~4 a; ?# o2 d% o
  4. using System.Net.WebSockets;
    4 g' o! G: t# d: U1 V' E& ?& y
  5. using System.Text;* i% l5 b" D8 p: q+ x
  6. using System.Threading;
    $ C" _% w' ]7 u$ ?4 F. k
  7. using System.Threading.Tasks;
    : k& L  l# O9 V
  8. using System.Web;; i8 J' G0 H3 [2 ~
  9. using System.Web.WebSockets;! p4 h& \9 q* ^( _5 O, Y
  10. ' v; v* |: x$ Z$ ]0 V: d2 {
  11. & i# C0 B4 O# z7 R+ ]* Z- S
  12. namespace WebApplicationWebsocketHandler
    * E6 Y3 @+ }* U1 r
  13. {
    " L& k! G1 j" J! l
  14.     /// <summary>
    % U" t+ I  T- }3 _; H/ L
  15.     /// 离线消息
    . }9 E- S0 w( y$ D
  16.     /// </summary>- ?) h( u# h9 r" x) O/ a
  17.     public class MessageInfo# {# Z2 l0 [7 ?. \/ n0 P
  18.     {
    ( x- g8 |8 x4 D5 ?
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    ! P5 ~, j& B7 m2 e4 d
  20.         {8 R  C, b$ `5 I( b$ X6 A
  21.             MsgTime = _MsgTime;
    8 T0 m9 V1 a/ L8 F8 H. m
  22.             MsgContent = _MsgContent;
    . b8 ]. P1 H; Q) N
  23.         }
    2 K, ^: f* H0 U/ T0 p
  24.         public DateTime MsgTime { get; set; }
    9 r0 t- x9 o$ Y( G8 j! P( D
  25.         public ArraySegment<byte> MsgContent { get; set; }8 c9 G3 ~5 G" m- q2 L5 v
  26.     }
    % f" v4 C2 v+ |( a/ \

  27. + {4 R/ j: ?6 n- E# ]
  28. ; [$ z4 }( e- b" a: M! h: v. w3 O1 ^+ V
  29. 9 U4 h$ ~) M2 N( L9 ~! V+ n

  30. ) ?& l- j6 Z- a% k. M
  31.     /// <summary>+ i; `4 g% }  Z, A3 \$ z
  32.     /// Handler1 的摘要说明
    / U) {. E) P6 ^& x% c5 }3 F
  33.     /// </summary>
    " P2 k- c0 L  [+ L/ D6 ~
  34.     public class Handler1 : IHttpHandler
    6 W" X2 y, T: ?, H# e) E
  35.     {7 W( e2 u: F3 d. Q
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    9 V% Z$ y" x- ?9 |9 {7 N: G
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池" W7 Q% t$ u2 K' N
  38.         public void ProcessRequest(HttpContext context)
    5 Q2 A7 ^4 w- j; i
  39.         {4 s$ _& |5 B" x' P* [" g& P* i
  40.             //context.Response.ContentType = "text/plain";" _+ x- N) f' S- `2 s# W+ }) c6 _, _
  41.             //context.Response.Write("Hello World");
    & Q" ?: J( ^- |. f$ d3 s/ `
  42.             if (context.IsWebSocketRequest)
    , ?3 o( K. t+ O+ s
  43.             {
    7 }; l: }' ^$ ^
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    : l5 E: j  A: m* n% ~9 t
  45.             }
    $ M/ C  o- f; o* d) C- V3 v$ T3 V
  46.         }: z9 Z4 |; S  m* g# q) \! {) U

  47.   N8 h" i" H) @0 `+ T* D0 _1 {- r
  48.         private async Task ProcessChat(AspNetWebSocketContext context)6 Y2 Z8 f: X  |8 U
  49.         {( z0 I, Y+ T! y: m2 c# _
  50.             WebSocket socket = context.WebSocket;
    ! G3 h$ W) D4 @0 h, w7 V2 j
  51.             string user = context.QueryString["user"].ToString();
    " l. H/ P9 j) F6 T
  52. ! e, Y' }8 x+ ?# L" e
  53.             try
    6 w! f9 T0 i8 x! t9 a
  54.             {) O3 _& w* k, y
  55.                 #region 用户添加连接池
    7 D$ q- Y" S4 H8 h
  56.                 //第一次open时,添加到连接池中
    4 I' T8 D  }# H8 T8 n. U
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    6 d. Q, u) N3 V. \& ]
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加6 ^9 J8 ?: x+ `$ k( k7 a
  59.                 else1 `: k+ g, G% ?
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    4 _* u. E2 c" j" C1 b5 P
  61.                         CONNECT_POOL[user] = socket;0 P/ H8 ^2 w+ M3 |  G8 v
  62.                 #endregion
    5 y8 Z: r1 Y, T* Q) M: G3 H- k

  63. 4 v9 W. N' f8 E" b! E% n# ]( ]3 \
  64.                 #region 离线消息处理& H6 J: c- D: J9 q9 ?
  65.                 if (MESSAGE_POOL.ContainsKey(user))3 C5 z  `- B) \- X; H& }4 f
  66.                 {9 {) n& w' K1 _  w
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    1 q& Y7 ]$ n: K; |# ]+ e
  68.                     foreach (MessageInfo item in msgs)7 a# O/ W9 ]+ r, n4 i" A' j
  69.                     {
    6 b3 u/ B$ L4 c
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    , |/ i" ~+ B# n# I6 @
  71.                     }
    3 k- ?- a" ^8 E# ?! q) a
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    - V# |( Z6 h- ?2 ]: V7 h% u
  73.                 }0 i& V3 W2 ]) G7 f, ^# q
  74.                 #endregion
    ( P4 a3 ~& I! R, U

  75. 5 s6 g" A9 r$ x% C
  76.                 string descUser = string.Empty;//目的用户2 T8 ^+ \; G% j3 j: e
  77.                 while (true)' q* I  h# _8 P
  78.                 {
    . e. O/ g: I6 f. t2 ^1 O
  79.                     if (socket.State == WebSocketState.Open)
    / \3 F$ @- u) w
  80.                     {
    8 s4 N7 v5 H' u9 i/ J( I, [
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);) o7 X: p% u( p  N5 R- B* P5 `  a
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);8 ^4 t) H0 k) I6 O2 a4 k8 i
  83. * D% d2 M" o* U- F% b& X! }
  84.                         #region 消息处理(字符截取、消息转发)
    0 |9 A: ^- l, N1 B) ?8 @) ?% E9 X
  85.                         try
    $ I$ ]/ l* Z2 V/ Y% l0 [
  86.                         {
    ' Y3 ^" C% l. B0 a
  87.                             #region 关闭Socket处理,删除连接池: M* o1 ^6 e7 A& l
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    7 l" i+ \3 k/ n0 k- F% d
  89.                             {7 b' }4 |% H) |& \
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池& _9 G  t8 G$ |& p8 N8 ?( G5 u2 o( A
  91.                                 break;
    ' E9 L/ o: ^; V. c4 ]5 i9 j9 z0 x
  92.                             }' D! l* L4 Y8 P% I: F. Q
  93.                             #endregion' q: S7 o) v' _" |. J4 U4 M

  94. 6 [# _8 |  H, D& r6 o
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息% z/ Y+ p, K" ~3 R  M, `3 v
  96.                             string[] msgList = userMsg.Split('|');/ d) }; D) @1 U6 u9 e
  97.                             if (msgList.Length == 2)
    5 s0 c4 L8 m9 ?; H7 N- B3 R
  98.                             {2 W9 {& B( J5 l. ]
  99.                                 if (msgList[0].Trim().Length > 0)+ Q- q* r1 S/ c: G. a4 L0 Y( A
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    $ U' @4 B  ?! O- I: [
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));- o+ V. C; H4 N2 I$ U% i+ z
  102.                             }
    & L2 m) L) e* I7 b0 v$ D) u7 q) g3 H
  103.                             else
    * C2 g$ i) p4 R# S6 b
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));. A6 P' h2 Z/ x% P, @* K: ?

  105. , Y0 O4 F3 R$ d* Y% V. M: n# h
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    4 z% I. y7 h4 l8 g' Z
  107.                             {$ f7 U$ R' w) S& W! o4 ^8 Y* J
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端$ G1 U' s+ ?, N/ Z4 X. a8 w8 @
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    , ~1 N, b  K! J& K
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    $ b! e1 b' D- A
  111.                             }
    3 I( ~0 D  ]5 L: v% T
  112.                             else
    % ~/ p4 N- N: r# V' f: x
  113.                             {
    ; {" F! m7 o( b5 W% X2 B% Y
  114.                                 Task.Run(() =>9 [2 x3 ~7 b# h
  115.                                 {
    ) L( Q) a, o, g) `# {' P( K
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    - R' h. |3 s- S0 m6 N' z
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());  z/ Q& C( y/ D% f- C
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息. y5 p- v8 x3 q5 I# W, w
  119.                                 });+ _2 m) h) q) r+ I- r* g5 r* U
  120.                             }* Z  t2 i! F8 s% A" n( O/ D7 O
  121.                         }
    ; }  `( V& x) ]9 t& F
  122.                         catch (Exception exs)
    ' \4 y9 m& H# I( ^: Z$ v
  123.                         {& Q4 z% i% t, ~5 {' L; s* q. R9 R
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息3 H' M2 w" K1 j! {( n6 `0 W- E8 {+ k
  125.                         }1 A; e3 o+ M: P0 O
  126.                         #endregion3 R5 E6 H; ?* @' K/ A) x6 n
  127.                     }8 i$ v6 j( H+ L7 {0 T
  128.                     else% D( C: s( |  @$ W5 K5 D2 g
  129.                     {1 _" ]6 L( W0 @( y3 c8 x
  130.                         break;
    : D' G" Y( z" k- |
  131.                     }2 d! h6 @" Q8 g& R; ~5 h
  132.                 }//while end
    5 G9 b/ [8 b$ K3 G; b
  133.             }( E9 t3 A0 c- Q: i* b: d! c; V0 k
  134.             catch (Exception ex)
    2 m+ l. P: u) Z1 Z% D* R
  135.             {
    9 X! `3 t4 n' h9 p) w+ `
  136.                 //整体异常处理0 N; Z# N( @4 ?# g
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    ) [5 g7 C: g5 s  z
  138.             }; a- n5 ~) e0 @$ X/ r' d  ]
  139.         }
    $ `: ?$ s8 r( C! a
  140. 8 u% n, F0 J. k/ k) N/ K4 w
  141. ' M: w* N( p6 J4 {
  142.         public bool IsReusable
    ' H4 A1 W" K  t3 q% ]
  143.         {
    0 D) l* A8 Y! X/ l6 ]
  144.             get3 P# X, A: t' g" t( H) M
  145.             {
    * r5 a* I  K& [+ y( M
  146.                 return false;; Z0 d2 i1 u9 [/ m. b) x
  147.             }2 C1 c. P# w  I- }' u
  148.         }# `9 ]/ H+ x8 b$ v7 j5 ]) Q
  149.     }
    1 c9 q9 g, f2 H+ O4 q
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
# S( B' H6 J; I  o' Y& |
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-18 21:13 , Processed in 0.114121 second(s), 24 queries .

Copyright © 2001-2024 Powered by cncml! X3.2. Theme By cncml!