cncml手绘网

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

作者: admin    时间: 2018-11-7 00:43
标题: 在IIS上搭建WebSocket服务器(二)
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
8 u! n$ L/ s1 d3 l# w! b9 T
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;0 U( U4 g7 ?) o$ l% ?7 D, ?
  2. using System.Collections.Generic;7 {0 t) ~) ?$ t  p! {* W
  3. using System.Linq;
      c1 F( b' ]4 R: B7 J
  4. using System.Net.WebSockets;- Z. q. S: X0 j4 }) U+ @: t- n
  5. using System.Text;
    " J& z( b/ m3 q6 s2 p
  6. using System.Threading;9 T$ A5 R) F! ]8 M( l" O
  7. using System.Threading.Tasks;6 }0 v2 C3 l  p; m7 k* s; i3 g
  8. using System.Web;
    3 _5 S2 \! z, N4 t: N
  9. using System.Web.WebSockets;
    ' K7 ]2 W; U* i. i) T9 P

  10. 7 W  ]" h7 E6 a3 I0 J/ k" h' Q* t
  11. * l9 h+ [7 f$ r% c( z
  12. namespace WebApplicationWebsocketHandler
    : l/ a7 L! u# X0 L3 L! G- a
  13. {- X; g0 Y' a4 F% S+ O' C
  14.     /// <summary>" X% I7 \5 Q' |' \9 f+ t% J4 k+ i
  15.     /// 离线消息
    9 ~! p* N) a; F; {) ]% {* w
  16.     /// </summary>& e% a. P' t- D4 b
  17.     public class MessageInfo6 l# U) x! P6 B/ \
  18.     {
    ' W+ W5 ?, ^  g' c
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    ; F$ g6 b5 g" w& P. R. e8 p
  20.         {9 }8 U4 y& s: ^8 L' V
  21.             MsgTime = _MsgTime;+ a8 c0 w5 V0 e9 ]
  22.             MsgContent = _MsgContent;7 S& e- i& l' k# D2 f
  23.         }2 ]# [! i4 X4 s' G7 y8 j$ T3 ]- z# {/ u
  24.         public DateTime MsgTime { get; set; }1 p0 F( c2 c' u8 B
  25.         public ArraySegment<byte> MsgContent { get; set; }
    3 j* T! {0 F- S6 N, @& z
  26.     }5 L; j& {; W! z" j

  27. 3 ~, A6 s" K5 U/ s2 ]2 J
  28. 4 O# |% ]: E' @& T
  29. & Z+ M8 l  V  ?( v9 z7 n4 Y! s

  30. 2 W3 O. c% ]& z6 h( T1 N
  31.     /// <summary>
    ! `- z; e. y+ q5 B- m( i
  32.     /// Handler1 的摘要说明5 [' e+ r' x, E
  33.     /// </summary>
    % i. J. c. N% y/ ^
  34.     public class Handler1 : IHttpHandler
    5 a5 x3 [/ Y4 U
  35.     {* }1 |8 U8 C6 t+ N
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池9 v$ C) r  ]/ j- |4 b: k
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    * O& A% ], ?$ I" B; W( w8 u& k
  38.         public void ProcessRequest(HttpContext context)' d7 J8 N1 z7 \: m  e( d
  39.         {
    7 G) H% \/ W7 j& i
  40.             //context.Response.ContentType = "text/plain";  u5 r- X/ I' n) g9 u) W7 P0 T
  41.             //context.Response.Write("Hello World");
    2 ]% w# S' r5 p4 Q0 T
  42.             if (context.IsWebSocketRequest)) l  `% @% P/ {0 F5 F8 O6 a8 o: T
  43.             {
    : }( b1 \4 S7 v5 v# X
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    8 m2 U/ [6 E! q
  45.             } 9 q, u$ U8 r5 _; @: N& G2 P
  46.         }
    3 `" b9 m2 S$ R/ [( s' I
  47. # g: b7 P( y* Y# N* W
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    7 _- d6 E) a1 e
  49.         {, B/ L7 R* Q3 f- P
  50.             WebSocket socket = context.WebSocket;9 b7 P% H' w3 K
  51.             string user = context.QueryString["user"].ToString();: _: J: X/ k( @# O( m! D/ g' K" h

  52. 3 b0 w6 R, b7 C; O& Y- ~
  53.             try- a2 v3 x- K1 _' _5 _2 y4 J2 g
  54.             {
    1 @5 k5 v" B( _
  55.                 #region 用户添加连接池6 ~0 X- w2 y# t0 E6 {" b& @$ I; D
  56.                 //第一次open时,添加到连接池中
    1 n  d+ W4 p# s% m8 V* Y
  57.                 if (!CONNECT_POOL.ContainsKey(user))5 M# N: ~9 m, R$ ]( T' P: _
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    % H+ I( c3 ?$ r
  59.                 else
    2 m- I( X; Z; @" W9 d, {4 ]
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新  u% o" U/ t$ ~3 e/ }' h/ i7 N1 ~
  61.                         CONNECT_POOL[user] = socket;6 n' o, s  u/ c$ Q: t8 h
  62.                 #endregion, y; J/ l3 t: ^3 y6 u

  63. 4 _6 b# n# q) X. P% S
  64.                 #region 离线消息处理4 q# N1 w$ j0 z& g3 L5 t% k
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    - l9 O5 i2 E* t. J* L2 d  D7 l
  66.                 {
    ! @9 v& m* o# c/ r- {) p+ T8 X% s
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    2 S: K3 j5 @9 L, j* i" p
  68.                     foreach (MessageInfo item in msgs)
    5 i0 e9 L: n  w; [/ {2 K
  69.                     {
    ( P* I8 x/ l0 M! Z' `& @* W
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);0 b9 O# u' c8 o* f. G
  71.                     }
    4 E9 d5 U- i0 y) z
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    # _3 W! T% n" s2 j3 Q' X
  73.                 }* q% e! O+ T8 Q8 w/ ~& y+ Z4 l
  74.                 #endregion
    " M1 N5 T3 i) j
  75. 4 u' z1 A- e8 @, ~2 e
  76.                 string descUser = string.Empty;//目的用户
    $ z- t, r6 d" F  q
  77.                 while (true)9 v0 @1 @* t- x1 S( Q
  78.                 {8 z/ x* R: w% l& t9 A/ }7 L
  79.                     if (socket.State == WebSocketState.Open)( P4 k6 B  H- L
  80.                     {
    1 b  n: j: |# }! c1 K% a
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    8 ~# n& t/ A1 }
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    ! O7 l+ N6 _, x" \8 x
  83. 5 G1 U6 W) I5 [; B4 `2 ~
  84.                         #region 消息处理(字符截取、消息转发)2 D/ C7 e: B" Q( U( S9 l
  85.                         try+ D( K, [4 P, {. B
  86.                         {
    # z; L; Z* u0 H& S/ P& f) Z- B: U0 i9 P
  87.                             #region 关闭Socket处理,删除连接池6 D: h$ Y; D! r# M; e/ `1 _
  88.                             if (socket.State != WebSocketState.Open)//连接关闭" K, U' e; B6 Z" c" b; w
  89.                             {6 ~4 x& H$ n' P% W6 k$ f
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池' e1 H6 G6 I: A: H% n# q  c7 V
  91.                                 break;( W$ j6 i  ]: d! k
  92.                             }& f% M( b, i2 T/ G' P. L8 r
  93.                             #endregion
    ; n1 g4 y( g6 T" A4 j
  94. ' a# N  r% [8 K
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    ( z9 \' C. g1 n0 w( ?( a; x5 u
  96.                             string[] msgList = userMsg.Split('|');
    1 T' \$ F1 y$ I+ }
  97.                             if (msgList.Length == 2): I( \0 N0 F9 j7 Y7 z
  98.                             {
    8 Y: x+ U7 [9 U0 Y* F9 W
  99.                                 if (msgList[0].Trim().Length > 0): ]1 y6 b0 u; [/ I0 E3 n
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    % D$ [! @) x, `- Q0 u. m( x
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));; K9 Z9 J0 C& Y. @% J8 h+ x! d
  102.                             }
    9 q# f6 w; X+ d( Y
  103.                             else
    $ q& [# B6 V1 r1 z% A7 @1 ]7 n
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    6 X& w1 ?# W2 t& d0 e

  105. 4 h( h7 m. D2 }7 k% [8 `
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    + R: v8 }' ]) d- ~, V! O5 \
  107.                             {
    % `* \- `$ a5 `
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    0 }# o# n7 @+ ]5 V
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)) }- z  {: q9 S3 p6 N: `0 K
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);6 c, f& [! V0 J+ \# y+ G
  111.                             }5 l$ N: p) g5 z% O
  112.                             else
    * Y* y* K  `  U" v6 i: f! N6 u" q3 |
  113.                             {
    ( w$ ~; D9 {# w& ^% b: c$ y1 }9 b
  114.                                 Task.Run(() =>
    ) r/ F" s+ H' |
  115.                                 {
    / b, d# c- i( u& |
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中  X% j+ M9 ]4 z9 K1 J
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());6 J$ D. h# T3 @( A9 h
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    , y2 u# ~! V/ c
  119.                                 });4 F# l; ^- |+ x" A  K1 _
  120.                             }
    + d. G0 {. U& X8 n8 \: o3 Y- z1 Z
  121.                         }6 t; m/ U. s/ [0 a1 v+ j& h
  122.                         catch (Exception exs)/ r/ Z  T: \" \7 z; [+ m9 w
  123.                         {
    - I0 A% S) y; ^, D+ i8 |& C
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息1 @4 F1 I: w9 K! [
  125.                         }  J* _# R7 I% f  n
  126.                         #endregion
    0 ]$ G- Z3 o* Z
  127.                     }# z, e% _% L1 p3 \7 T  b$ Q
  128.                     else7 ^! u2 s3 K% K+ q" Q
  129.                     {
    ' j  {$ F& }- C3 C/ [4 t: C
  130.                         break;9 p" S6 @5 x# j- B3 g: k
  131.                     }) F  X) y& b+ ?
  132.                 }//while end7 x8 z8 [0 D+ ]6 x
  133.             }
    ( c5 o% R* _1 [$ [% r
  134.             catch (Exception ex); Y3 n: q. S- U& b% F2 t
  135.             {
    ' P; j: b9 C5 R$ c; m! i1 P! Y% J
  136.                 //整体异常处理
    7 E% r8 w6 a6 K4 P7 x
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    ' |8 _0 S2 d5 S8 D
  138.             }* l+ U1 C7 k8 h+ d0 d( I( s
  139.         }
    : o9 \& o5 d0 v+ v( X5 ?2 F6 }
  140. ! F' q6 N$ V" e

  141. 0 E7 Q6 \6 U: l1 ~( o# Z
  142.         public bool IsReusable
    / P6 j; c( q1 x5 x- m
  143.         {
    7 v- O+ L: m6 U
  144.             get
    : t* K7 Y" h" f5 W9 b/ s/ B- d
  145.             {
    6 X' J, t& k. g# L& ?
  146.                 return false;3 s4 n5 e+ k/ z* u  Z
  147.             }
    ) e9 C, m$ W5 G9 D  y4 L9 P& ^9 Q
  148.         }
    / K" N3 C6 S9 j% I7 M- q
  149.     }
    1 S5 r) @# |& p1 S# R- z
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

3 d6 z3 u& l' j* k  N4 q




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