cncml手绘网

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

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

$ K8 |5 j2 R- b2 X1 u" E
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    ) ?& O0 s0 ]0 l8 n6 t5 p, t
  2. using System.Collections.Generic;
    0 Z8 K) w8 Y6 I- `/ D( _
  3. using System.Linq;" C) K  o  ]! Q! o/ F
  4. using System.Net.WebSockets;
    : `4 z. U" N* f+ U
  5. using System.Text;
    4 y: P; |+ ^5 K9 F/ G+ k2 X  Q
  6. using System.Threading;
    # ^) {' |# @- m+ U8 c# P
  7. using System.Threading.Tasks;! Q: m! p$ p5 g# a5 m7 x
  8. using System.Web;
    ) m0 Q) u1 K' ?& V
  9. using System.Web.WebSockets;
    2 J0 M+ z' O- U

  10. + B& N; H8 d2 a$ z; T: V5 K
  11. 5 x9 w& s6 c+ y& o4 C
  12. namespace WebApplicationWebsocketHandler
    & O1 n  H+ G" G6 B* k$ |
  13. {
    . r& I. A. [# x
  14.     /// <summary>
    ' y% G( a/ U0 o' c1 x. z& R
  15.     /// 离线消息3 I) p8 C- T) z/ v
  16.     /// </summary>
    # V% D4 W' q! E6 e" s& M
  17.     public class MessageInfo
    8 ?3 \* n5 k( z2 t' t. v
  18.     {, w! K$ ~, ?+ }) K
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)6 E0 |; s# `3 W0 U- ]/ q: s8 B
  20.         {. S' d, F) r0 b8 k8 z9 O3 w7 K
  21.             MsgTime = _MsgTime;* Q. f6 ~4 v. X4 B
  22.             MsgContent = _MsgContent;2 U& s  M; M$ {% {; P/ T" |% s
  23.         }- i9 {; l; J; E4 ^
  24.         public DateTime MsgTime { get; set; }
    9 X6 \# ]( E) F: W+ \
  25.         public ArraySegment<byte> MsgContent { get; set; }* b7 f/ K" V3 v0 c2 N
  26.     }
    5 u" F2 i. D4 i3 e3 @5 B

  27. 1 e8 t; z- H; s( E

  28. $ m2 _( d4 p$ Y1 m  T0 N& Q' ]7 ^  J/ q

  29. ; N# r6 t% a- i1 e  U) _! _
  30. 0 V8 i* ?3 e- H2 y7 V* A2 A
  31.     /// <summary>$ B  Q5 n! E9 ]
  32.     /// Handler1 的摘要说明
    # ~( {4 B. G7 i0 x
  33.     /// </summary>) C# J% ~9 n$ h5 D# w& W/ t' c
  34.     public class Handler1 : IHttpHandler
    " q* L) x) D+ ]( {0 ]
  35.     {
    ( F  v- f: j0 F2 b/ [3 k
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    9 H- B/ i  U6 g  r* ^
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    9 {& Z$ H; L( b0 {9 T+ t  z
  38.         public void ProcessRequest(HttpContext context)
    ) d' l1 ~# x) H! b8 D& N5 O) P
  39.         {+ C. [8 `. v/ M4 p- q
  40.             //context.Response.ContentType = "text/plain";
    , t- Z  U2 F' z' C; L1 z$ v2 v
  41.             //context.Response.Write("Hello World");0 u& Q9 s' W9 k- [3 p
  42.             if (context.IsWebSocketRequest)
    0 a* R; X7 {2 `4 m7 L4 K# {
  43.             {7 {: a. V8 z: {& }" F( Y
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    : h2 o1 A& f3 j
  45.             } 2 `. z1 r& Y2 H9 G" c+ K
  46.         }4 F+ w; e% t( ~

  47. 6 p" V2 T# B# p' o" c
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    5 q$ l0 Y( ^# c+ c+ X4 z2 p6 y1 k6 Q
  49.         {
    & u2 _% Q7 j# U# `
  50.             WebSocket socket = context.WebSocket;& P& Q* D! ~$ N/ J" i
  51.             string user = context.QueryString["user"].ToString();3 _# w0 m& b$ S

  52. # F/ C, j2 R% G
  53.             try. {  Q' x; N- e8 d2 z/ E
  54.             {& ~$ k' Q- i* L& b+ P$ }
  55.                 #region 用户添加连接池$ b, x# M- B4 s
  56.                 //第一次open时,添加到连接池中, t- r6 }( y+ l: \: p4 {; w
  57.                 if (!CONNECT_POOL.ContainsKey(user))8 ^$ _8 A! g6 D6 p+ A
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加1 k8 ?( f  B$ O! C; ^4 P( o2 j! C
  59.                 else4 a* Y8 T" y4 S, U3 y! a- U1 p
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新, ]/ R+ T$ j8 [  o7 ^
  61.                         CONNECT_POOL[user] = socket;
    / E  z+ X' Y6 I+ u7 m8 ]# ]
  62.                 #endregion
      z" A- i, ?1 j% O2 V# d. ?% u
  63. % o# D% C- l7 ^/ C$ A$ u& s& e
  64.                 #region 离线消息处理4 ^- v+ @5 E& Z) i2 m
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    * k' I# ~2 F& r3 E+ ]& d* K
  66.                 {
    5 P7 B! w( C2 ~
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];7 i; G( z4 ^# {, y
  68.                     foreach (MessageInfo item in msgs)
    # V% Z, A$ `4 \
  69.                     {; ]$ {& H3 X/ C! s
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);9 K+ n" g" w; r  u* H- G# s4 Y
  71.                     }
      |4 `# M& R$ {+ P
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    2 w, E# t0 R1 N& k; g: J3 {
  73.                 }: f$ P! D8 x& g* l7 R
  74.                 #endregion
    - N( ~' y5 `4 k; v
  75. ' A: F0 h% _: M
  76.                 string descUser = string.Empty;//目的用户" a. {+ `/ F7 H* o
  77.                 while (true)
    " {' X+ S+ T9 a. V+ Y) {: F; ~
  78.                 {' q: }3 t& q( u
  79.                     if (socket.State == WebSocketState.Open)
    4 t7 O. p; C9 R( A$ M
  80.                     {
    ! R% Y6 u$ g. P0 N8 R( h
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    ( y) i8 i! c+ t0 i2 Q7 Q$ R" \( Z4 V
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);% M6 u2 G; W  T- g( U

  83. , k1 [3 h3 O6 T1 v6 ], L
  84.                         #region 消息处理(字符截取、消息转发)3 v9 d; w" x' K  g1 f  ]+ n' v; D/ [3 m
  85.                         try
    5 j3 q0 @1 z) S5 ]& B
  86.                         {! v& K% O& R* n- q/ v0 G: [
  87.                             #region 关闭Socket处理,删除连接池: K" d9 b' d* o) U
  88.                             if (socket.State != WebSocketState.Open)//连接关闭6 ^" k9 j  j) E9 ]/ Z
  89.                             {: c6 E& F. P6 x* @% M
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    ' v6 q, T0 E( T" T
  91.                                 break;
    + f7 d+ k! A/ r
  92.                             }
    & t" t! m$ Z3 |* Q' [. U0 u
  93.                             #endregion! ?" \& A) N4 X6 b: x
  94. 1 P( S+ ^4 Z8 n5 |4 i* r. Q2 ?: Q9 U
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    7 ?! T# P3 u, E- l* Z
  96.                             string[] msgList = userMsg.Split('|');
    % o( R3 }* [# g0 g, ^0 Z/ A
  97.                             if (msgList.Length == 2)
    ( q$ d9 O% n0 b, Z" H+ d
  98.                             {# G2 c4 H. ~* l3 c& [
  99.                                 if (msgList[0].Trim().Length > 0)* C0 m6 L* V+ c% A! j5 L
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户% @1 f% C4 B. W: B3 [- j1 B. P4 V
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    - J6 }! |+ B0 m! `3 L/ W% {, z% A
  102.                             }9 y$ P& D! _9 m$ Q5 `9 I3 {1 R8 ~
  103.                             else
    $ S2 G( R1 G2 r# x
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));0 h  B9 s' m1 d3 H- v
  105. ' {* J/ z8 v6 b0 r" U: s
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线* [8 @# U9 R/ R# G$ n
  107.                             {8 s( W2 S; A8 T, I
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    ' W1 z: J4 `! k: c+ j( z
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)& I$ U$ X! g$ j% V" q+ R
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    ' T) S6 [0 N: x) \9 N; \
  111.                             }& c1 q3 @. h  k: r
  112.                             else3 X. O" g- J' p. Z
  113.                             {7 ~- }3 s8 i0 O/ `( d1 g$ Z
  114.                                 Task.Run(() =>* p1 j3 {, u8 g6 i0 C
  115.                                 {) H( U( v* q5 t6 f% F+ y
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    ; G, S2 a& k1 e$ V1 U
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
      x/ u9 c; {) H7 R
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    3 C! u5 A6 a4 \  o& L4 p
  119.                                 });
    3 M& K; W2 O7 e6 k
  120.                             }
    7 {$ M! \7 n+ N9 ?# }
  121.                         }0 b3 P- I& |: Q& L6 y/ S
  122.                         catch (Exception exs)# d# Q+ H* O+ M' a
  123.                         {' |1 s# Y: |) a8 M
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息) t6 o3 u4 T( z! G# P
  125.                         }# {; P% j" e$ Q
  126.                         #endregion8 n; n0 B' G; p: ^+ z; ^
  127.                     }
    ( n8 R0 r7 m# i6 V6 K
  128.                     else
    - z  `. f% k, s/ N1 }
  129.                     {: L  R7 T* B3 `3 |6 C
  130.                         break;
    ! {3 ^2 m; x) q: m* V9 Y1 l
  131.                     }  f' {6 z2 \! b
  132.                 }//while end
    % A6 Z( v' _7 @: a
  133.             }) K" m, Z# p4 v) G
  134.             catch (Exception ex)
    ' x* t  V$ Y  Q1 O. [7 M- F. M5 r
  135.             {
    . H' A# G" ]6 X# V  `- U5 |
  136.                 //整体异常处理, B# ]5 l+ _+ l$ W
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    4 Q, V- _! f+ i/ }  D( z% {+ d; d
  138.             }4 N1 W- z" B! p" f, v# y
  139.         }
      R. C3 l2 v) \# A  ]

  140. 9 K8 g0 M% \% E. \2 M" M( g

  141. , ~1 u( A: o. l" X* n
  142.         public bool IsReusable0 L, H$ N! x: p: B# a& S
  143.         {/ r/ ?. J% ^6 n" t
  144.             get$ K# z5 z' F( ^9 k/ G# f1 g+ u$ p9 C; a
  145.             {
    + B% [! T6 n3 k& T, g
  146.                 return false;
    - C  C) Q: K) n$ f
  147.             }8 k$ X+ N, Q( {. }: k* L. [! o
  148.         }
    1 ?$ w( N4 h) H5 V5 z# _
  149.     }# I+ L1 R; a5 D7 g7 f
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
. ^0 Y4 S/ k& f. ?





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