cncml手绘网

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

作者: admin    时间: 2018-11-7 00:43
标题: 在IIS上搭建WebSocket服务器(二)
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
. s+ d+ L* g; E& U& |; W$ g
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;% h; _6 H3 f4 r$ h
  2. using System.Collections.Generic;
    8 R" R5 m$ C! m  a! E/ Y
  3. using System.Linq;) Q* S/ h6 x% B& |2 W) Z  y
  4. using System.Net.WebSockets;. A& `- t% C* W  c% z8 X; d
  5. using System.Text;7 n" b3 N  W. b* L0 K% N
  6. using System.Threading;
    . m% l, f( U+ Q- ]6 ?" g; T
  7. using System.Threading.Tasks;
    " q5 T" @- x6 K$ j* Y+ @4 A
  8. using System.Web;
    9 n: @& h: b% x2 _8 h0 j
  9. using System.Web.WebSockets;
    9 B' i+ V+ |( a3 D
  10. ( A- D' c4 I$ y* a3 j
  11. 1 T4 d# P7 P; f" n: e- B1 h0 h: u
  12. namespace WebApplicationWebsocketHandler! n- @; V# E) G1 _
  13. {# _8 h$ C- `8 n0 t; H) L. ]
  14.     /// <summary>
    . o) w! k; Y8 _; ]( t% ]* N
  15.     /// 离线消息
    ) `0 f* t2 \) \/ {3 Z  c1 m
  16.     /// </summary>
    " Y) t/ H+ Y, v, g) @7 ~* i! s
  17.     public class MessageInfo) f/ n* Y7 W0 ]; a
  18.     {6 A# o( e: z, S; v1 G0 w
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)0 f/ a8 Q9 ^! f7 ]: {& c3 }
  20.         {
    ; p# `6 i3 f+ ^6 U6 I! F$ d
  21.             MsgTime = _MsgTime;! x2 V7 ^+ M' \3 F7 m) Q0 C7 r
  22.             MsgContent = _MsgContent;2 ]. p; I& D+ `! U
  23.         }6 I6 f/ O2 m8 M! x; |8 a
  24.         public DateTime MsgTime { get; set; }
    - _$ a( x# Q2 q* P* h! h9 Y
  25.         public ArraySegment<byte> MsgContent { get; set; }1 w5 l! e* E! x* t
  26.     }
    $ N' o# x9 G7 ~6 ~: h
  27. - I% }5 u& C: s9 m

  28. 4 |, p- W, l. x& J7 O* ?6 l

  29. & P8 h  m5 _/ }7 U
  30. / `% ]. f2 y+ V$ O/ c3 j! f
  31.     /// <summary>
    3 d5 k" v' R# A4 f) T7 X
  32.     /// Handler1 的摘要说明
      t4 b) y% g! E) q& G8 t) [$ O; M1 G
  33.     /// </summary>
    # G, ~$ G: k" a- E, z* H3 K7 r
  34.     public class Handler1 : IHttpHandler8 ?+ K+ x2 ~' d4 ]6 x( i# x
  35.     {1 p4 e# A2 m5 p
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    4 c: y6 O1 U3 w$ \: L  t& ?, s' }, i
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    + ~2 E6 U: ]8 {- x
  38.         public void ProcessRequest(HttpContext context)
    3 W& W2 W  v5 E, r! Q2 X1 f
  39.         {
    4 ^9 k8 Y/ }9 V
  40.             //context.Response.ContentType = "text/plain";
    - j  H" N- Q" M2 }
  41.             //context.Response.Write("Hello World");$ Y0 I' h" p+ ]. a9 O
  42.             if (context.IsWebSocketRequest), X- {) K4 ~3 D$ o+ B9 E8 _+ s; K
  43.             {$ a. o; |# O( m  n$ D; W9 u- d
  44.                 context.AcceptWebSocketRequest(ProcessChat);+ y  p# I! m; i
  45.             }
    - ?& G, x- c# z" Q
  46.         }# b1 G% ^8 c$ n. N4 s

  47. - C" I# o% i, c7 B( J2 f
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    , ]. L1 c9 t+ z! t3 W
  49.         {. n' K0 m7 Z0 D& [& H  w
  50.             WebSocket socket = context.WebSocket;! H+ W: S7 G5 S% G0 G& W) D
  51.             string user = context.QueryString["user"].ToString();
    # H. d7 D5 N2 F0 [: V) C) J8 O( k
  52. 8 \, }9 H# z: E  M  ^
  53.             try
    5 m2 }0 B; c+ f; C8 e
  54.             {' h+ t2 o$ n5 X7 W6 C
  55.                 #region 用户添加连接池
    ) l; L3 X; ?* k4 q
  56.                 //第一次open时,添加到连接池中5 {% L- Y" _/ R  X( d& K
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    3 Q9 L  {2 l1 D- ]
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    - b: }  P7 c- j5 Q7 O2 S1 Z6 B& C
  59.                 else- m& \6 k9 N$ T# o7 i6 q& \' F, H( |. K
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    , C/ m+ Q0 X. T7 F$ j8 \
  61.                         CONNECT_POOL[user] = socket;. ^9 p" @1 D3 ^! r1 {& P! r
  62.                 #endregion
    * g3 h; q& u  P5 _4 l, Z( b) `
  63. 8 E! X2 Z  K1 G  M% G1 x
  64.                 #region 离线消息处理9 n! l3 z* o9 [4 c9 o
  65.                 if (MESSAGE_POOL.ContainsKey(user))3 a$ l9 |% K6 K0 r- z) u# H
  66.                 {+ s1 s) X6 }; |8 V0 S
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    3 B- Y& s6 ^; Y& O1 e
  68.                     foreach (MessageInfo item in msgs)
    / M- V# l$ f7 {' R2 A
  69.                     {
    3 w3 V* |" l& Z& z+ b. g5 m! @
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);$ G* u* ?& {: I6 E. k: I! W
  71.                     }
    , F$ K8 o( d6 n9 ~
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息8 L& x0 U4 ?3 s  [5 p7 j
  73.                 }, b2 ^& Q) P' q$ f6 d! b, p  A5 U
  74.                 #endregion
    ) K& }' D) Q8 c) l) I
  75. ) I! E5 W2 y+ R
  76.                 string descUser = string.Empty;//目的用户
    % h% R5 c( b5 o1 _2 |
  77.                 while (true)7 A. A& j1 p/ }* A
  78.                 {
    6 o) o. Y; b6 Z! N
  79.                     if (socket.State == WebSocketState.Open)
    8 w4 e( p3 J7 s1 z& c* q1 Z
  80.                     {
      [% j2 n  J5 W5 V
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);9 ]$ }* C) W5 X% g9 F
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);' v6 K( m0 g; j, E1 T8 b/ S
  83. # j' Q9 u" |" ]$ S5 Y
  84.                         #region 消息处理(字符截取、消息转发)3 Y. l: x, Y+ w" `' p3 h+ b! a3 ~
  85.                         try
    : C: W7 I+ {; Z: G( l: D* P1 W0 W
  86.                         {
    $ x$ \2 ^6 t2 \5 G3 q
  87.                             #region 关闭Socket处理,删除连接池
    4 h* B9 J3 U. i" i
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    0 z9 P% Z9 B- l. Q' E
  89.                             {
    4 q4 b/ P4 K8 w, k1 i
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    ! |+ [0 p# N% n! A; k8 V
  91.                                 break;
    / ^$ ?) K3 T0 l  D- {6 q$ v0 L
  92.                             }
    * x* ~8 B8 ]+ n7 K5 b
  93.                             #endregion
    * O) |& D: I# _. `

  94. + p/ A) `5 ^7 D6 m, j
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息% d0 K/ w9 O" V  i& j3 N
  96.                             string[] msgList = userMsg.Split('|');9 U( k: B* \7 T7 C6 b/ j& H; E
  97.                             if (msgList.Length == 2)
    " @- p! t( k7 U
  98.                             {
    ) ?- k& `" x0 n8 U# Q! G0 _7 J. o; `7 \
  99.                                 if (msgList[0].Trim().Length > 0)
    ' F# G# @5 Q. r! U% ]
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户7 O9 @/ m, ^0 \6 s0 q5 {6 M( M
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));) O3 S  x& I: l  W) [
  102.                             }# N1 E% k; V, A( c7 J: D. g( h+ v
  103.                             else" ^2 r5 {1 T" G2 I7 N- s4 A! y
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));. a& j9 h1 d% j2 C2 @4 W

  105. $ K( m8 o  |% \' x& ~. S; J* w, w6 K
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线4 q2 A7 {7 `' p
  107.                             {
    / J% R# G! I. g( ~
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    * h* H1 A2 B& g9 |
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)8 K3 q5 \% Q* p, V" G* h, s- [
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);1 M' g3 p7 ]6 `
  111.                             }
    ' F% h3 i- u( v2 u' D' k
  112.                             else) i5 k: J- S7 {+ j7 F3 S
  113.                             {9 o- T; \7 [- n+ }. C: c
  114.                                 Task.Run(() =>9 i; W9 [8 l8 M0 F2 n& [7 |+ u
  115.                                 {
    8 n0 p$ d6 N1 z: P1 U  `
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    ! \; @- v* `' I3 y
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());! P$ T) E3 Z" B* u8 @- i
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息" v6 s1 O$ ^. v2 m4 b! W  G8 ^' T9 \
  119.                                 });
    4 Y0 O9 h3 F- D! ~
  120.                             }
    . v4 q$ X) l* w2 m9 [
  121.                         }
    + \+ I. Y1 Z5 `8 j( N% Y8 F
  122.                         catch (Exception exs)
    / E' L# R+ G2 ]! z
  123.                         {
    3 }4 q+ b# t: I7 j
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息) s$ G# {1 g. K, Q2 b" ^
  125.                         }
    / A3 T( h# ~( ]( r9 k: q- N4 {' k- z4 n
  126.                         #endregion
    8 a% Q, h* v8 e0 T6 l. d
  127.                     }- d5 [1 ?0 n1 z* x7 S; K
  128.                     else) j. a# w! L0 W0 k" t- w
  129.                     {
    8 V" W& T* R2 H1 w
  130.                         break;. A5 T, `% K" _* c+ t9 w8 d# S
  131.                     }
    + C9 R" C+ A& b! y
  132.                 }//while end5 d6 q, i+ M2 b+ `
  133.             }/ S( s# d0 x3 ~- U- l7 t' ~
  134.             catch (Exception ex)/ p) ~1 X. a# G& f& q
  135.             {' v" }# e3 J$ B4 `$ }
  136.                 //整体异常处理
    , {8 p# z; F0 [" Q6 z- Y; _" ]4 f
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);2 L9 @4 x( L* Q& g
  138.             }) M/ k' D: p/ f, o0 d) X  _
  139.         }
    $ w. x  F. F$ m; ]/ G
  140. - Y/ Z! ]  b% T9 J. N5 T0 E  a. z
  141. 5 T; H2 c! y1 J) A
  142.         public bool IsReusable0 ~. h/ V1 f, e( s0 b9 X7 u
  143.         {7 c8 l: r' u$ v0 A7 d" p+ z
  144.             get* \/ f' V+ U# T) {! @
  145.             {
      p; r/ Z. s6 P( F0 ]2 _
  146.                 return false;
    7 _5 \" U9 K$ N% M7 L( K
  147.             }
    3 e1 \! S( W' \9 Y4 B0 @* z: ^
  148.         }
    6 L% i3 ~6 Q0 d
  149.     }
    + a: U$ u( S  |5 A$ Z  p% [
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

+ d, y; w6 r. \/ T




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