cncml手绘网

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

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

& b+ j+ F2 C! T' Q+ N- M* f
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;8 j1 A+ Q( L- a/ B, }" P
  2. using System.Collections.Generic;; f) c6 x$ k! z2 n4 T0 ~* j
  3. using System.Linq;( b( }% `9 R; R# c$ J0 x7 H8 K
  4. using System.Net.WebSockets;
    " [4 f$ X" i) H) \4 D
  5. using System.Text;7 h( M" t7 [5 n& Q! G
  6. using System.Threading;3 J2 b+ ]/ t+ R0 C3 ?
  7. using System.Threading.Tasks;
    / D+ y, h$ [1 _" b, o, W, s2 @6 d
  8. using System.Web;
    3 W8 P, P* i  `& R4 l  |5 _
  9. using System.Web.WebSockets;
    9 N3 F  k9 f3 u: I

  10. % ]! ?6 P$ C1 R" g: S

  11. 2 T% k' {% `7 x, A/ f- ]- g
  12. namespace WebApplicationWebsocketHandler
    , W* ^+ o+ ]) H7 P; `; @) x0 o
  13. {' z  U, }/ o" e) s; \
  14.     /// <summary>
    7 Y: h; M# L& b& b5 z4 K8 v
  15.     /// 离线消息
    ; j; ?) b# T7 w7 D
  16.     /// </summary>
    7 f. H& r$ u7 L* l' t, _$ S
  17.     public class MessageInfo# N* `6 e3 W5 A# I! w& c
  18.     {
    ' O+ B3 |8 Z2 m: ?1 s, d& z, j
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)- q0 V" B: s4 J6 G3 ~; E
  20.         {
    ' s$ }0 d% e- x, _' a6 S: F
  21.             MsgTime = _MsgTime;
      a" J% \- ~9 h2 C: D  U
  22.             MsgContent = _MsgContent;
    2 Z: N7 V3 w  v
  23.         }
    2 i  }- A3 l, [: I
  24.         public DateTime MsgTime { get; set; }6 z" ?( S9 k- h
  25.         public ArraySegment<byte> MsgContent { get; set; }6 M! e/ f/ a4 j2 S+ K3 Z
  26.     }
    5 K' S1 ?! W: O

  27. 2 K, r8 O& \/ E! U" a7 s

  28. 4 X& o2 H% V. Y: f8 ?1 T

  29. 8 L) X+ B9 u  V9 N! U& F) T
  30. 3 E# C- o9 M( J6 X$ d0 @4 z
  31.     /// <summary>
    & Z. r0 m" ^. M2 W
  32.     /// Handler1 的摘要说明7 r) V* q/ G# X& `: \% ~" C9 Y; }. w
  33.     /// </summary>
    ! r1 }" @' M' A# \  ~) C
  34.     public class Handler1 : IHttpHandler
    - _% Y8 a5 O/ z" @
  35.     {
    ( c/ t$ b9 k; {4 Q5 T  b
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池9 W( O1 W# N& v( X8 I- Y) |: {
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    & P$ _) Y# f- W6 A3 Z
  38.         public void ProcessRequest(HttpContext context)' [2 U5 W/ |; F3 f% ?0 K' k
  39.         {/ R- _* [  u3 y4 ~1 `$ P, a
  40.             //context.Response.ContentType = "text/plain";' B6 D" b: f7 \) {
  41.             //context.Response.Write("Hello World");( x# S  `+ \* J8 `' q
  42.             if (context.IsWebSocketRequest)$ y+ F3 ^. q& X
  43.             {/ N: k- l; e) h
  44.                 context.AcceptWebSocketRequest(ProcessChat);3 e7 B1 E. M9 X3 f4 N3 h+ m
  45.             }
    2 {, P. y* J$ b/ `( m
  46.         }
    1 S$ R( ]; k0 d/ |; Y1 y) R' m" i

  47. & @5 u. ~. i7 q% N0 d0 p# o1 C
  48.         private async Task ProcessChat(AspNetWebSocketContext context)! ~" R/ ~; x2 S
  49.         {5 q4 {# B# T" f0 N. @9 e# N/ F
  50.             WebSocket socket = context.WebSocket;& Z/ t7 ]4 L; j/ u
  51.             string user = context.QueryString["user"].ToString();
    1 `* Z# \% H# w0 w1 P4 R

  52. 3 \' u' F3 m3 H% R% X3 W5 L
  53.             try
      X& Y3 B4 @- h  Z  k7 B
  54.             {
    1 n  c  Q- W" M& B4 W$ \
  55.                 #region 用户添加连接池
    3 c; J. J( d( R! Z! U
  56.                 //第一次open时,添加到连接池中
    % Q1 F# Q, D8 g& E
  57.                 if (!CONNECT_POOL.ContainsKey(user))/ n- V, U  T+ u- s/ H
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加" H8 r) x' d. m9 C& B! h6 \* F
  59.                 else
    ! W  Z# |" D5 S
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新% e+ V1 ]) v1 {- G
  61.                         CONNECT_POOL[user] = socket;8 n9 O+ ?/ U# ^% R
  62.                 #endregion
    9 F" z. o/ Q" t9 h0 E" k: q0 J  V

  63. * F. ^& a+ g; m% x) v
  64.                 #region 离线消息处理" R' o+ f2 j5 g6 E% [1 O0 g
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    + o- N! |% i6 ]( y0 A/ Y  Z
  66.                 {
    % o/ ~, W: l: I6 W+ q
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];3 {6 h, Y( h1 E/ ^
  68.                     foreach (MessageInfo item in msgs)
    % ]3 m. ^3 A0 G  z$ X
  69.                     {# Q8 n% A- l9 L7 P; ?6 R
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);( P9 X+ S: |, N, g- h
  71.                     }
    6 D) [. z  Q2 V& @6 @
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息5 D4 T7 F5 s& M
  73.                 }2 Q' O! S* \+ Y+ Y& X2 T
  74.                 #endregion+ r; D$ L5 U; h( [1 x

  75. ) ^5 b; J- q7 f+ V; s
  76.                 string descUser = string.Empty;//目的用户
    6 [( ]$ P, Q5 v- v& M- R
  77.                 while (true)
    4 [& a8 T- y+ p
  78.                 {5 }1 U, h) [! R  l1 I
  79.                     if (socket.State == WebSocketState.Open)
    * {% X8 }' F8 e. X7 a" L
  80.                     {
    " N. |% D& j; j' x! ]4 R
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);; B- u7 C  ^- g
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);0 p" c" r$ l3 `, K& }' }+ E

  83. ) w# D9 g3 V1 S% Z% p! b4 g* u" o
  84.                         #region 消息处理(字符截取、消息转发)
    ( X. m) ?' u. ~4 [- T3 I" s: n9 Y
  85.                         try4 P2 u  X5 v- P+ h
  86.                         {
    7 B2 H$ {; T5 U, h
  87.                             #region 关闭Socket处理,删除连接池- D9 I$ n2 z6 t% j1 l
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    ' q) a3 k8 q; F( x6 \0 {
  89.                             {
    4 d0 D" @! m0 e) K3 m- @$ V& ^& x
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    2 N, L, {5 _* d
  91.                                 break;# N* ?+ Z( N4 |
  92.                             }
      e$ K( G8 N# S+ Y
  93.                             #endregion% t+ x+ X- m) Y9 J
  94. $ C9 ?, y2 w4 ^* e
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息5 K6 G( w  ?. _1 \
  96.                             string[] msgList = userMsg.Split('|');
    4 U# L& w. N6 @  Y. `' V: }" k
  97.                             if (msgList.Length == 2)+ x$ x9 ]! Z' t4 I; H1 E7 w
  98.                             {
    ( r# j/ q/ v; n% ?8 m8 M- n
  99.                                 if (msgList[0].Trim().Length > 0)
    ( a2 T- o+ s4 P
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    : x6 h) e/ l; B
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));/ X7 Q$ B: B& Q: a1 M8 m6 X% Q* R
  102.                             }* D( Y1 Y; _2 M* @7 A% `& [
  103.                             else
    4 v5 w) L/ J* y6 J* }* J8 A
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    / X2 \5 |$ i, r, _
  105. % f7 x1 X% `( d! v% W; @
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
      v' `. q3 T, a+ v' f! ^# A
  107.                             {7 \$ O# [3 B( E2 t2 c, q
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    ' Y9 R4 d% t) ~9 c
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    0 h8 B7 f& ?! r& _1 n" e
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    + H) s" `2 Z" i; V
  111.                             }
    1 P! d8 {8 u( U" Q" d
  112.                             else
    # Y& _/ J5 M- t) S
  113.                             {/ B* M1 T& \$ \' ?. r; q4 j
  114.                                 Task.Run(() =>
    9 ^% [( K. L) n
  115.                                 {
    $ [/ m, T4 u( L- n7 B1 @4 z/ y
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    0 m& F" B0 Q0 m. W% J
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());. Z" |- B! Y6 c1 X; T
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    8 b; P& J3 u: f. |
  119.                                 });8 }% N" C' @. r& I/ H8 W8 {( D
  120.                             }
    3 j/ E8 h" c5 l1 Q; G
  121.                         }
    & Y+ g% W# p, ~. ?
  122.                         catch (Exception exs)
    ! i1 B: L8 Q/ k# E. p' Z
  123.                         {) d* `+ X( z4 C/ R% t$ S+ Q6 v
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息# z+ ?: n6 t/ D# X, b
  125.                         }
    3 y0 f5 |: ]1 D1 Y9 i
  126.                         #endregion
    - h6 f" o! X& q5 L) K, @
  127.                     }
    ! B& R0 }0 c; [# m9 Y' `
  128.                     else
    / X' v# P1 }- }. q/ I# r3 A
  129.                     {
    : X' W- Y3 n$ p( n
  130.                         break;' J; ~- O9 h% M9 m- q- S. v- B
  131.                     }
    9 b- ^. E2 M" i$ E& Y
  132.                 }//while end
    : K! Y: a8 h7 T
  133.             }0 s& ]# l: \& K3 g+ i
  134.             catch (Exception ex)8 b9 b. ~- e& u) l
  135.             {6 F! a6 |2 k' K3 T9 v* U9 T# q8 w
  136.                 //整体异常处理) D, a' \4 A$ L& B6 L/ L
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);! d. g8 z7 V5 ~, g9 s' t
  138.             }) B  n! l2 |7 J$ ~/ Y, w
  139.         }5 r) h1 r; C) U2 Q8 B; ]

  140. : E% ]3 W* _7 e5 |/ {" P4 Q/ r# K
  141. $ _; u# i& N) U# D$ y
  142.         public bool IsReusable
    + L) S& E7 _* @. z4 o: Y6 L4 L
  143.         {
    ! l: M- `8 R, H; L8 ?# f
  144.             get
    # O8 I* j2 s* k& X
  145.             {% X! w  b1 m+ n- Z5 [/ l; U- m
  146.                 return false;; y" B9 V; L$ G( w, L
  147.             }
    , e# ?( P& D9 y
  148.         }
    . N2 I" k9 b3 w% \
  149.     }
    ( w4 D* T4 V  Q0 r# G
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
8 H  ?8 r* [: d" j8 `" [0 S





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