cncml手绘网

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

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

, ?# W$ P5 q+ O  O$ v
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;0 P; A; V, U- C% ]9 {
  2. using System.Collections.Generic;
      G" L/ m. s6 W
  3. using System.Linq;$ z, X- _8 F  Y# q6 v, d: T1 t+ P
  4. using System.Net.WebSockets;
    9 ~6 J+ W' x5 i
  5. using System.Text;  k; _6 o$ A5 B6 w
  6. using System.Threading;
    ' ]6 d% q3 P9 p3 C
  7. using System.Threading.Tasks;
    ; q# Z  G8 i7 `
  8. using System.Web;: r4 U. }- k$ f6 `" W* h  J
  9. using System.Web.WebSockets;
    ; l" B8 r5 K4 x6 x/ k

  10. , l* r% B' p' p1 I

  11. 6 @, r. D! t5 s3 _7 @! D2 W$ s
  12. namespace WebApplicationWebsocketHandler) W) Y3 T$ o5 O; E* j
  13. {
    3 t3 y/ o  \3 v: }4 p6 {, w+ \
  14.     /// <summary>
    3 l3 S7 t9 ^; L# ]+ Z" `! D
  15.     /// 离线消息
    2 o1 Q; V! K3 _
  16.     /// </summary>
    + g- z9 c( W& C3 q1 s3 q
  17.     public class MessageInfo
    : l7 h- y4 f! j) S% \
  18.     {/ n7 {, `7 u4 S1 s4 E# }1 g+ c. W
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    / B# Z; i& V/ m: V
  20.         {9 A4 y* P) r4 T
  21.             MsgTime = _MsgTime;' F# _8 S4 \# h$ V3 |& }4 B& J. e
  22.             MsgContent = _MsgContent;
    7 L- x/ x" Y2 r/ f% `( ]  b
  23.         }! W3 W$ D  f" B* o
  24.         public DateTime MsgTime { get; set; }
    + f" `6 w, e5 p/ D; Q! m
  25.         public ArraySegment<byte> MsgContent { get; set; }
    8 K1 Q( `$ X' ]+ h1 N
  26.     }: m1 Z% S% d6 e) @# R
  27. 3 y/ j2 H0 Z% M& `+ j+ I  w

  28. 5 H- m" E7 A( t6 R& |) N
  29. , H) E6 B; U8 j/ S7 f4 t2 w
  30. , E+ l9 K( Y3 B, Y, c8 |
  31.     /// <summary>
    + I& B) H* X9 g! D* G) q" K* h
  32.     /// Handler1 的摘要说明9 r9 B# o; F& O8 @
  33.     /// </summary>4 Q; F/ l4 ?$ _" G. F3 R7 ]& ~
  34.     public class Handler1 : IHttpHandler
    ; a+ }# [, t! E9 b# Z
  35.     {
    8 K5 ^7 ~1 `1 `$ K
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    5 Y1 H0 {* o( \: x
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池1 o* d* c1 R" O/ ?" ?9 f( ?
  38.         public void ProcessRequest(HttpContext context)0 |& j* N+ w# m8 |) b6 X0 `4 z
  39.         {2 T( x: ]$ A! ?( }/ q4 `& \5 B
  40.             //context.Response.ContentType = "text/plain";8 n0 A- ^8 Y* b0 o3 n0 n
  41.             //context.Response.Write("Hello World");: q) t; C/ p2 g, `) s) m5 a
  42.             if (context.IsWebSocketRequest)
    0 u6 A# C- }# @( e0 [
  43.             {
    ) z, K5 S+ j, q. A
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    # U1 ]/ X% b' ]1 G
  45.             }
    4 D. k5 m  H/ x! h; w; D
  46.         }
    8 k$ ]# M4 r2 z* a

  47. 7 \, k' ~* z+ z) c2 F8 h& g
  48.         private async Task ProcessChat(AspNetWebSocketContext context)9 n" n& V6 ?% P6 M" {7 N
  49.         {( D: A5 ^% F  ]0 \1 ?# h
  50.             WebSocket socket = context.WebSocket;
    5 n5 A5 m8 z0 Q# r* b+ C4 n. V
  51.             string user = context.QueryString["user"].ToString();
    5 X) ?! z  S: i4 o
  52. 2 z2 G' N% r8 u3 {
  53.             try
    3 @2 G1 ?% Y, L
  54.             {( f2 ^$ ]/ h% i$ p; v
  55.                 #region 用户添加连接池; x/ c! \6 g1 d* t' I# S/ d
  56.                 //第一次open时,添加到连接池中
    3 O  j& `$ p& C2 x7 @9 H
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    ! `4 q! _) j7 J. v2 w9 W$ j, P
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加$ V- L! h9 G6 a" ?
  59.                 else
    7 d: k3 H8 h! O- s  x
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    ) f, B8 g( F2 N
  61.                         CONNECT_POOL[user] = socket;' p2 G- G% f2 K  f/ C
  62.                 #endregion$ R% L: w) T6 T  d( b# D$ D

  63. 7 s& ?- t3 s$ Y- ~. s
  64.                 #region 离线消息处理* T5 E1 R& k/ @4 N
  65.                 if (MESSAGE_POOL.ContainsKey(user)): J6 M- r6 \' |* X
  66.                 {$ A, Y! r- v) Z$ V
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    # \/ P# _/ e1 P' K2 `7 Z# V
  68.                     foreach (MessageInfo item in msgs)) R6 M2 U% x3 f) E5 }) o6 i0 k3 C% q5 l
  69.                     {: y! N) V/ a% s" x( G$ ]
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    1 S- b* X; j: J/ `  Q' i1 o% f
  71.                     }
    5 n  I$ ~+ P2 L1 Q! I( R
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息2 n3 W/ T/ d! G( a% p
  73.                 }3 [, g0 j9 f; M: u
  74.                 #endregion
    9 L6 d! i1 ]2 q0 W. B! j

  75. , ~. i8 f5 r) \1 r& ~2 N
  76.                 string descUser = string.Empty;//目的用户
    1 ]" W6 }2 d7 _, y" k0 W
  77.                 while (true)$ y9 V5 `' ]0 h* c
  78.                 {
    * X3 s: k2 L2 h  }
  79.                     if (socket.State == WebSocketState.Open)
    , i0 [) R7 H- [! F) J6 ?
  80.                     {  q7 f4 T2 o0 M
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    ' t2 p, S4 v6 u5 n* e7 \3 l: p6 D
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);$ O; z9 ?* V$ `% f0 T
  83. 8 z# }6 x, ^" N+ F! D! [- N
  84.                         #region 消息处理(字符截取、消息转发)+ p7 Y- Z1 P! f/ a" R7 x
  85.                         try$ t8 h- Q7 _$ X& {# P4 a- ^% @
  86.                         {
      s! o: E' W% s
  87.                             #region 关闭Socket处理,删除连接池; }9 @9 v9 C# V# d' @% B$ c
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    ( F  A9 i  `$ C2 X4 b$ W
  89.                             {
    + `; c! ^& F- o1 G$ }" N* R" }
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池0 ^+ D& y( W* r2 F
  91.                                 break;1 {2 u2 `' T( Y. [, v
  92.                             }: y9 F' c& ~* K; Q7 O2 G5 C
  93.                             #endregion
    # O# z+ y5 D% |# I" t6 t
  94. 6 @9 `( `$ ?+ L
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    ! H6 ~# Q- _0 \1 ~4 H
  96.                             string[] msgList = userMsg.Split('|');
      T) u( M/ K" X) Y. Q* ]( t
  97.                             if (msgList.Length == 2)
    8 ~6 L8 K0 E; L& S# y
  98.                             {
    " W; E2 [4 u2 R5 c1 e! h/ v
  99.                                 if (msgList[0].Trim().Length > 0)' s& }1 Q) d* F) J- ]. j& ~
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    : a# f! S$ [$ I( H( E  W2 P
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));9 ]  ~* Z$ }/ x0 M' K
  102.                             }. L( I  B) w) i0 O3 T3 ~; [  F/ o
  103.                             else
    , ~  G: p1 d! E" l+ Q. G5 O! E
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    " ~. d7 ~. m4 O- I) g
  105. * @3 }7 @: _  ]3 B9 L
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线9 }0 x: U1 y! C% _3 s
  107.                             {* Y( |" `( U* h; |
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端8 O% X( |& R- N2 x: S8 v
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    0 k9 t0 t2 }/ m+ c2 _; o% t# j0 `
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    / Q" c& @6 y: j3 C
  111.                             }* q3 d- F, i! t1 j8 K& u
  112.                             else; o. E9 E  Y  T6 h% r+ L
  113.                             {
    - X8 r' V! B  m& k3 a2 Q! n2 a, \
  114.                                 Task.Run(() =>2 K7 Y8 F* I  _1 t4 j
  115.                                 {% {* K& F. }$ B: V( F
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    - i. |3 m' z- [- b6 q' q  U9 S9 {( I& m6 ^
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    ; {2 T& e+ l8 k$ p2 U1 H0 L
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息* ?5 J( E' g3 \% B9 ^/ F% s0 u" c
  119.                                 });, T& Q& x* g5 Y! n+ ]" ], O
  120.                             }
    / k1 g4 ?% V# B8 \$ q
  121.                         }& _+ b* K1 T5 ]4 {3 z' {0 B
  122.                         catch (Exception exs)- U8 P- Z9 q7 x) a1 M/ x
  123.                         {
    4 a' ]. h# ~; X. v
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息! ?* e5 J4 _5 |4 A, c
  125.                         }
      r" g3 W0 Y$ O. l2 ?$ q
  126.                         #endregion
    5 f; }  j% u, U. R
  127.                     }, z0 I$ R9 @! @; I! s; I0 Z
  128.                     else
    6 S  u+ ~; Y! Y1 d; ~" Y
  129.                     {- S6 c0 ^4 I5 ]4 t
  130.                         break;
    + I) i1 \- ~* q
  131.                     }
    . `$ V  b, I8 l$ C4 w
  132.                 }//while end
    ( D+ L: |" [: ^8 [8 ]
  133.             }1 `3 _: E2 c. {
  134.             catch (Exception ex)5 i0 O* K3 {# z  m! e" y; g' {
  135.             {+ ?' I! b4 F. \- i1 ~9 M/ v, Q0 R
  136.                 //整体异常处理
    ( D! g% j9 E/ A: h
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    9 ?& `* g) a  h/ I( o9 W
  138.             }
    + G; Q0 N4 _0 F
  139.         }, u7 w) @0 z* R- `& f' [& g

  140. 5 j( ?+ m0 I: ?' f, M
  141. & e* l" s, p4 {
  142.         public bool IsReusable1 s8 z! A" Z7 g  E
  143.         {
    - p' Y- r: ]% `% W. b
  144.             get
    7 \2 k, t+ g! o; _$ [1 H
  145.             {; u/ V# \6 ^  T- m) E
  146.                 return false;  m& [/ n; N1 q8 O; _8 z& l
  147.             }
    / y* Z: ^  M9 a% M4 ]6 b$ ]; i3 f9 y, X
  148.         }) P: u$ u9 |1 k8 k
  149.     }: Y. v5 q0 K, \3 \+ i9 S- p. j
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

, Z( ^  W  e& b& f9 u' C




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