cncml手绘网

标题: 在IIS上搭建WebSocket服务器(二) [打印本页]

作者: admin    时间: 2018-11-7 00:43
标题: 在IIS上搭建WebSocket服务器(二)
服务器端代码编写
1.新建一个ASP.net Web MVC5项目

& m% ]: N8 t/ [
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;5 A+ M! K0 R9 B
  2. using System.Collections.Generic;
    + G6 n8 ^8 h9 u* [* z0 J
  3. using System.Linq;5 l, \) a/ P1 w; j
  4. using System.Net.WebSockets;
    / J5 P3 u9 r* ~- c' z" C
  5. using System.Text;
    / C$ @6 E& ]6 ?: X
  6. using System.Threading;
    3 k/ n( |+ D2 s/ R+ M0 i, z
  7. using System.Threading.Tasks;
    * T0 l( C+ g: [7 j& B, z9 D+ X
  8. using System.Web;
    4 _/ A5 w" Q7 O. i; R, L+ H
  9. using System.Web.WebSockets;) K6 B/ M' ]( P/ j) ]' v9 T  `$ r2 U

  10. * V' L9 I: {1 U" P+ R$ o7 u
  11. 5 i$ ?4 i) \( C1 b
  12. namespace WebApplicationWebsocketHandler
    9 N8 y4 m& ~( ?1 a
  13. {* x  U* `! V! Q+ T) Y0 U
  14.     /// <summary>
    ' V2 B. C2 i; v, Z* Y
  15.     /// 离线消息# X4 A0 l6 c1 d5 ?4 n, f% R
  16.     /// </summary>
    3 ?9 ]" h% C+ f" R- d' C. F! l
  17.     public class MessageInfo0 J- G5 |, b( z# ?9 t4 _8 x
  18.     {4 [' b4 f1 e* Z% ~
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    + g7 o! c/ Y! j
  20.         {
    ( N" F& j% x. c6 h( l& `/ }. g
  21.             MsgTime = _MsgTime;9 g9 t( j8 F. ?8 [0 b; @  T
  22.             MsgContent = _MsgContent;
    8 W+ l8 d0 d0 G
  23.         }, c$ D& k7 t3 u% Q$ e4 |, C5 G0 d
  24.         public DateTime MsgTime { get; set; }
    7 H9 s  b+ ^. a! ^+ E
  25.         public ArraySegment<byte> MsgContent { get; set; }$ R: t% n: l* w- V5 @
  26.     }
    * t3 J; x) n& F6 m$ G

  27. ( Z* [5 q4 _- l! D
  28. 0 x! c  Z1 ?: ~; D& @7 |3 f! q) Y
  29. 9 g) w# W. {! k& ^

  30. 9 J8 Y2 e) [: A
  31.     /// <summary>
    - G& x' o( t' W; t8 ]* ?4 O, }8 r
  32.     /// Handler1 的摘要说明
    - b* m" i7 c" h2 i8 w
  33.     /// </summary>0 |1 w% b# I8 q0 U8 p) k; u
  34.     public class Handler1 : IHttpHandler$ A! b- P; P9 V7 G
  35.     {
    + x/ E4 l) w" ]
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池0 J4 |: k; B; a' k
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池& d1 b  [) m7 W& Q
  38.         public void ProcessRequest(HttpContext context)
    3 l$ ?( `1 }6 W" D
  39.         {
    9 J; `5 w8 d' p9 X
  40.             //context.Response.ContentType = "text/plain";
    ! {0 ?, C& ?4 E/ Y1 u0 ]. n1 h
  41.             //context.Response.Write("Hello World");
    0 V$ W* Y1 k0 |+ e9 E
  42.             if (context.IsWebSocketRequest): r% f0 R: h) ~6 b+ {- `
  43.             {
    & [9 O6 S! ^. Y
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    , L% ~  @; L  a3 N. y! \
  45.             } : j+ V/ t4 v  P9 E9 \4 ]3 u: Z
  46.         }
    . n1 I; T/ }5 C9 p0 N! L- v6 G
  47. ) H: a/ w/ k- L; v" ^, A
  48.         private async Task ProcessChat(AspNetWebSocketContext context)& D* ]7 p9 p) r" q
  49.         {8 Z3 T5 P1 T' @& R, z7 Z
  50.             WebSocket socket = context.WebSocket;3 z; `2 Q- A) N- W+ o
  51.             string user = context.QueryString["user"].ToString();4 {7 K7 {! N  \- }9 i
  52. + S! _# ]: L2 G! u4 y6 }0 `
  53.             try& ?* [% [" x/ ?1 _
  54.             {  N3 g! [6 i  @
  55.                 #region 用户添加连接池% \; V( n6 h0 R1 ^. ]" M- N1 T
  56.                 //第一次open时,添加到连接池中# k- D$ b% B- b8 A% x
  57.                 if (!CONNECT_POOL.ContainsKey(user))+ f/ ~+ a* _% U  c* S
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加& g, e% Y+ n" V% C$ A8 d! P$ s
  59.                 else
    7 h( g0 Q2 B8 r( f: [
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新9 \- K( U( ]. a& l! q5 Q- K3 j
  61.                         CONNECT_POOL[user] = socket;
    9 M8 Y( @' ~0 [2 x: N
  62.                 #endregion
    5 k4 R4 ]+ v. R8 J! U1 {
  63. / n1 f- b7 K6 O0 M
  64.                 #region 离线消息处理4 z! r  ~8 `. P$ {4 M
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    ; M8 t6 m$ V. p$ u3 W4 Z. A
  66.                 {/ q1 m3 r- \* S1 k: M* c- Z8 X
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    5 R, N3 p+ g& J+ o" A, `
  68.                     foreach (MessageInfo item in msgs)
    8 F4 H) B& V0 u& k5 h" i7 [1 L, [
  69.                     {
    7 u6 r! T! s  i7 Y+ I4 _( l
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    $ z; u& n  ?' T7 a. @; ^7 {
  71.                     }7 l1 S& X, n( z4 k. w
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    + F8 f: R; E1 a
  73.                 }
    . s" q3 n$ S; _- N% X
  74.                 #endregion
    ; C2 n% o) I/ F
  75. 1 o; Y1 J& K! c
  76.                 string descUser = string.Empty;//目的用户$ q8 U  h$ I; V% `, h6 W
  77.                 while (true)
    1 U' e9 o! @3 }6 @# v7 p
  78.                 {
    7 O. c- B- b5 ^7 @
  79.                     if (socket.State == WebSocketState.Open)
    - H0 p' L4 G2 j- D" Y9 ?
  80.                     {
    3 D: t3 U5 N6 e9 b) l, ~# q
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    ! k& h( Q$ O( o! |7 m+ ?' l
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    9 ]* F0 J. p6 A( |* s) b
  83. : E# O, P5 c" m$ I& j
  84.                         #region 消息处理(字符截取、消息转发)% v( F7 D1 x0 a! G5 Z: h9 F1 Z
  85.                         try
    1 y0 v  J; q4 o3 Z& w
  86.                         {
    % d( R6 ]4 a, v, u6 g
  87.                             #region 关闭Socket处理,删除连接池. S% [' I" E- g
  88.                             if (socket.State != WebSocketState.Open)//连接关闭) ]% v/ }) o4 U! D
  89.                             {% v" ^5 U) ]' |3 P3 G4 |: |
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    5 j2 G4 y9 W) u  Q0 m8 h
  91.                                 break;
    5 K2 Z4 A9 {$ U2 K: C! \
  92.                             }9 V  z# I% G7 O7 }2 y
  93.                             #endregion
    * j2 Y! x/ _7 q/ O* C+ W" o% Y
  94. " o5 W  k* Z/ Y% s" M
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息7 Z4 N# M3 S! n
  96.                             string[] msgList = userMsg.Split('|');
    * T3 c$ U! G6 l
  97.                             if (msgList.Length == 2); v* `0 V, O) z: j% A8 Z6 _
  98.                             {+ m- |$ {, v. j0 Y' u- I9 M  H
  99.                                 if (msgList[0].Trim().Length > 0)
    9 \# g  Z0 ]- H# j2 t+ O& ^
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    % S$ Z/ n, O. D' g7 _- s: K# v
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));" o8 P/ j0 _, d4 B" c
  102.                             }7 u* i) O) R0 @( @1 k5 k! ?) [
  103.                             else
    . Z# S! O* W) ]
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    # W! O% ^+ j. z. Z; _

  105. ) O2 n% c& L4 _! S* Q
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线& S' Q$ h+ A3 L% g, g/ b
  107.                             {
    . P/ b9 V: P8 K
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    6 B1 u9 a6 S! h4 i2 P6 D6 s
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open). e" |# i! e7 F' r* K; G2 L
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);  S4 a8 U: ]$ O: i4 Y- e) \
  111.                             }* A; A* f% N; b9 t- n6 t
  112.                             else* s/ s7 j( Q  p+ N  F
  113.                             {
    , J/ F- y8 D& w8 q- B) L/ Y
  114.                                 Task.Run(() =>" W9 R4 A# r$ K8 k& N
  115.                                 {
    9 c- E5 s. D- n  @% A
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中5 k$ i) r8 P% S. R* L& n! Z
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    0 M6 @3 k, l+ n) G0 m! q0 B
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    ( @* u5 r* F) R3 c+ x2 `6 L( Q+ p- l# y
  119.                                 });
    ! P, ^2 n9 V4 }/ z( S; t
  120.                             }
    ' R1 x6 n0 U+ P$ J# Z
  121.                         }
    3 K, ^1 ?* u1 q7 q$ L) k/ F' Y
  122.                         catch (Exception exs)3 d3 h9 K0 k1 j
  123.                         {
    ; l6 N. e+ i2 b' H
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息! g3 ?, g. @3 P' @2 R" e
  125.                         }
    5 m: ~: _# {7 _% @: F
  126.                         #endregion
    2 A* y# B, A0 b7 u9 c# u# s8 i8 }) X
  127.                     }  F0 q1 `5 Q  \
  128.                     else/ S- u; n# I0 O! ?3 A" u( P$ R
  129.                     {; \! \" P/ f: O: {3 B
  130.                         break;2 T7 Y  Z: Y2 j$ N, i
  131.                     }' _' M  K. A) K0 _% }: z2 ^
  132.                 }//while end
    / y' q1 F/ a( v. p8 W4 ], G& ]1 y: N
  133.             }: P3 Y) ^' I$ A3 ]; i% ?& R
  134.             catch (Exception ex)
    1 J) }* I" R( W" z
  135.             {
    3 Q& y4 t' S, M& T8 m
  136.                 //整体异常处理; O$ @" l& S1 q: o  H) H
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
      j" B$ ^+ z5 O* V1 Z# o
  138.             }
    8 m; `, @; r; d. H, Q8 f
  139.         }' \  v; z7 {; v- v
  140. . E+ Y- E6 m* h/ s) ~- h- o
  141. - \0 ~5 T, r9 ?. S
  142.         public bool IsReusable, Y! L9 `, J: W5 g$ B4 f4 Q
  143.         {
    & w- y& T$ |) G0 M" G
  144.             get
    . u6 \* Z* k5 A" v$ O
  145.             {
    8 y1 I; r. q8 V' `" r
  146.                 return false;5 }& S5 g. p0 G3 w4 D) g2 s/ b
  147.             }
    . ]7 K# X! A& K  S7 A: z1 x
  148.         }0 U9 ?: ^# j- p5 W% Z$ `
  149.     }/ b& o/ \. B1 A) ?& s4 Z6 W
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

' I. W0 i$ b" i' N




欢迎光临 cncml手绘网 (http://www.cncml.com/) Powered by Discuz! X3.2