cncml手绘网

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

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

8 k7 Q! E4 Y' R; x5 r  k& e
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
      f* p8 t" v3 N% \1 L5 g
  2. using System.Collections.Generic;  d1 @: y& E0 Q) H- \; m
  3. using System.Linq;' e  O; M& k' E4 Z3 A& a& E' X% O
  4. using System.Net.WebSockets;
      }* u4 G" ]# H. T& u, J
  5. using System.Text;
    & M- k9 b6 b% u* J  A! |" M
  6. using System.Threading;
    1 U$ c6 {: f; T# x" V
  7. using System.Threading.Tasks;: l+ x! v- j1 Y4 z
  8. using System.Web;
    # \( H8 p. |8 Z
  9. using System.Web.WebSockets;
    + T) ~, h0 ^0 t; u0 l
  10. - o  w3 W$ M; l* S# @
  11. & v7 I" v& W% E
  12. namespace WebApplicationWebsocketHandler( c4 s( A( y# B7 V
  13. {% N9 r4 f) f& f7 \7 v7 \9 B  D
  14.     /// <summary>
    ! U( {+ u  i0 S$ s
  15.     /// 离线消息
    $ b5 o, l- {8 o
  16.     /// </summary>
    $ j1 l/ h2 ]0 E2 O( O4 [+ a7 O
  17.     public class MessageInfo
    6 g, K: _  X; _; l6 x
  18.     {$ v) m6 @5 m& o$ h& y
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)  ]* X, p# ]& N
  20.         {  S" l" P0 O- d0 Z0 G1 `  z- m
  21.             MsgTime = _MsgTime;
    7 H4 l7 K* q+ O8 c+ z& {4 n  L
  22.             MsgContent = _MsgContent;
    1 c. j0 v( `/ y) ]0 {
  23.         }$ _! Q6 M2 I: o! y. o9 w, w$ D" Q
  24.         public DateTime MsgTime { get; set; }
    5 R+ Y6 n5 `! S* D$ |# l" l% M
  25.         public ArraySegment<byte> MsgContent { get; set; }
    & e# A& b: X# q8 I+ m! R' L1 v- m
  26.     }, l% x+ _1 Z% s" q( s' s8 b# k" P) D
  27. " d( f) r; ~2 i. q" K
  28. 8 A% p5 E% }% M/ T2 O7 ^
  29. 7 h  u; v1 F: T, E
  30. , R  u1 i/ D' {0 R# u6 s0 w
  31.     /// <summary>
    7 T3 n1 y* u9 i6 A& f, y8 d( l
  32.     /// Handler1 的摘要说明
    & h, X5 v$ n; V7 P( g' u* z
  33.     /// </summary>  c  J" j. k3 Z/ j# Y5 S
  34.     public class Handler1 : IHttpHandler3 \4 R/ T) J  }! h
  35.     {
    - F( }4 I' V$ ^4 v$ w2 a2 J( N
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    * {: K9 E9 u; i, N$ F5 P0 G# F( J
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    5 L  c0 ^% |) L# S
  38.         public void ProcessRequest(HttpContext context)
    4 V8 a/ D* `- \% H
  39.         {! L2 y' E' k. g4 K& Y
  40.             //context.Response.ContentType = "text/plain";6 R9 ^0 w% [4 U6 C% ^8 b; Y
  41.             //context.Response.Write("Hello World");
    8 ?+ P; e8 @7 ~% J& {
  42.             if (context.IsWebSocketRequest)
    # T$ O" o$ b5 \* }, V
  43.             {
    , E6 g7 Q# _+ i2 _1 U* l* E) S% a
  44.                 context.AcceptWebSocketRequest(ProcessChat);) n4 p0 @" t7 @+ q
  45.             }
    ' D+ L# t3 |- `3 R) V* H' w
  46.         }
    , I/ A# d$ `# ]

  47. - t; q* \3 l: l* C. `1 d$ G
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    7 ~1 y7 r- ]2 T7 u4 S: I
  49.         {
    2 _) j2 h: k) B: ]4 [6 k
  50.             WebSocket socket = context.WebSocket;+ B, h8 K+ v2 C
  51.             string user = context.QueryString["user"].ToString();
    1 E+ g6 Y6 W2 U( v& n
  52.   I  J5 y9 k5 ~. Q
  53.             try& N) u# [3 Q, [3 W
  54.             {- B& f6 i! q  ]$ |- {% L
  55.                 #region 用户添加连接池" E! b: a7 {" P" r4 x/ z# |9 j8 ]
  56.                 //第一次open时,添加到连接池中( U" v5 h1 }4 r
  57.                 if (!CONNECT_POOL.ContainsKey(user))  V+ E2 D0 K" i6 Z
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加5 a$ n! m6 E$ Y4 ~
  59.                 else
    7 K) z# E7 u  [2 X# q0 s
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    2 }0 Z7 f% B  q) n* F$ C
  61.                         CONNECT_POOL[user] = socket;
    8 e% f$ F& t5 b* E3 t
  62.                 #endregion: f" e, ?7 O" s" a* j

  63. . J* l; v" y+ N" H6 s
  64.                 #region 离线消息处理
    9 r: o8 E  N4 s# j7 ?
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    , e( ?: w- p  V% e8 q
  66.                 {
    5 v, A3 X' y: e* G
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];; ], j! D1 T$ {. V
  68.                     foreach (MessageInfo item in msgs)
    7 h1 y& {9 y, F5 L- S3 u  o) U
  69.                     {& [: U- W% J! J3 {! M
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);$ {& _6 P. `: V7 [# Q
  71.                     }
    ( B# y5 u% E; B$ s" W3 k0 d4 r
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    9 L8 `! h, O+ s5 h, T) m$ i
  73.                 }1 a+ I$ e4 M& N! b3 i9 j
  74.                 #endregion& b) q! A# m! n+ R6 U% c
  75. 7 `6 W6 z# q; I" q
  76.                 string descUser = string.Empty;//目的用户
    , d( d* C2 R$ L9 ^' M6 d  j
  77.                 while (true)
    $ d3 A# L. C$ A* |0 J1 X; Z
  78.                 {' y) _+ H  L) Z8 Q- O6 D
  79.                     if (socket.State == WebSocketState.Open); U, q6 J3 x" s
  80.                     {2 t& Q' w2 I5 M4 j  W8 I( E
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    # G  r9 A% ]$ `; h' s) L
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);" k; A( c: L7 t2 p1 `1 y; C

  83. & U- b- Q2 Z. r& Y# P- k
  84.                         #region 消息处理(字符截取、消息转发)
    , H% O. E3 A2 ^! \
  85.                         try
    + K* r" m3 H; `( c$ A; t
  86.                         {
    . O2 ~# t# t$ w. g1 c8 V7 A, Y) a/ d
  87.                             #region 关闭Socket处理,删除连接池
    ' @+ I& @  W7 W2 Q5 f. [- q& x
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    2 g6 l+ D3 o/ n6 `* ~6 W* Z6 E
  89.                             {
    ' y' x7 G+ m1 D; U3 \
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池5 G6 B# X$ p/ w9 V  q* J7 P! F1 i: ^
  91.                                 break;. x2 z7 T, i$ N/ V7 M4 S
  92.                             }5 ~7 z, Q2 F' A6 }+ {) o" R
  93.                             #endregion* b8 F/ g1 b: M) V
  94. % Z$ ~& A; H* ~
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息4 L" T6 }! H3 ~$ A; [" p' I
  96.                             string[] msgList = userMsg.Split('|');
    3 o( T  Z* C( [+ y3 H/ T6 ^# p& y
  97.                             if (msgList.Length == 2)1 O4 N: l8 M! [7 p' |2 F
  98.                             {. u8 L* D- B  T
  99.                                 if (msgList[0].Trim().Length > 0)
    # n- T4 s% v, f
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户% f) n( C- E0 ^  y
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    0 Z) r( B# p4 l, G2 P, F
  102.                             }
      t9 e$ P0 r8 A# U: ^/ W9 `
  103.                             else/ Z3 B& F3 S! Z
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    4 H- k1 `  D! w- V4 O) m8 [
  105. * K1 G" b6 Z% {; g% @' u
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    ( S2 p& D: V/ c6 x6 Z
  107.                             {$ w' C+ T  _( @; q, u. ]/ Y' p
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端) K, [- }3 m% }  }
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)$ Z2 C1 B( u/ F$ o6 I% x% C
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);4 A. O/ j) R- @4 V" k
  111.                             }
    2 j/ m: r: T" u3 N$ R  H. k0 e
  112.                             else3 A) [! ?9 \' f
  113.                             {
    7 s* p6 \3 O8 y  g. m0 G
  114.                                 Task.Run(() =>
    & z- y4 \, x4 t5 u4 N8 j: g: @# T
  115.                                 {' ^( ?7 c0 R7 R- u6 r9 H4 @
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
      Z; U, _  m- j
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    5 @* I% O) \: A  K
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息, ]! f$ `  ]$ u, D, P
  119.                                 });
    5 ~; m: w  q/ }" M8 j) C
  120.                             }6 \4 s9 b9 I0 o0 p9 S! z
  121.                         }
    2 b% O* x; l% w  ^: M/ M$ Z/ C
  122.                         catch (Exception exs)
    8 H8 V' \' T' A
  123.                         {  S. E  _- p1 |& T/ h$ \5 @, [
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息$ N1 b. Z3 Q% M* ?
  125.                         }2 X; y9 |9 P+ w) Y/ l
  126.                         #endregion
    9 X  l$ }3 C* S, N) }2 ~: N4 O
  127.                     }- B( _9 `. w# ~( I) k& d
  128.                     else" O* l$ ~% o, N% c+ O
  129.                     {# j! S3 g3 }( v9 }, S
  130.                         break;) k. R' f9 u; B* u# P. O
  131.                     }. f; ^6 @1 p0 O3 j$ p6 _
  132.                 }//while end# Z" m, U8 g; s; }$ F! s5 J& f
  133.             }
    8 _' H' @, q% z' L5 K2 a0 I8 ^
  134.             catch (Exception ex)
    . h; v# K2 ]7 Q8 K# k8 _) E
  135.             {
    & U' n% y$ L3 p* p4 v2 T( D+ i
  136.                 //整体异常处理
    # G. [/ K; i# S0 w* J0 {4 a7 @
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    ) T9 f% R) K: V+ o
  138.             }
    " e; w4 R% f, m
  139.         }
    . r4 }$ Y0 q$ y# ^0 [: m0 w

  140. % u( O2 V# @  d1 c

  141. + G0 r, I$ }/ b2 K. F4 e( _. u
  142.         public bool IsReusable
    * `/ s: G. p  U& b1 z
  143.         {
    9 ~" U; F9 `. N+ `! S) z
  144.             get$ f# n5 H0 M: g/ B
  145.             {& K; m1 O( q/ \+ h5 c, }% A  `( s
  146.                 return false;
    + ~+ Q5 A$ ?: D4 _$ _# b
  147.             }
    6 J. Q; u' `, }  j
  148.         }
    8 K5 t4 }6 g( W, j; T
  149.     }
    - w0 T  R8 f+ k7 R( r% Z2 q
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
5 O2 I& m, u# O





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