cncml手绘网

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

作者: admin    时间: 2018-11-7 00:43
标题: 在IIS上搭建WebSocket服务器(二)
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
8 m: c# F, ^, J' y8 |3 j
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;; {( F; x% j: j7 g
  2. using System.Collections.Generic;
    " O; o3 Q' O" W/ `8 O! e
  3. using System.Linq;
    # q% ~, F+ v; _, ]: K9 z
  4. using System.Net.WebSockets;1 V  k5 o0 n" C+ j" h  Y: H3 {$ q
  5. using System.Text;
    - v. z- u- @/ z# b! \2 p) w
  6. using System.Threading;* t) S2 C: `. Y2 e( ?
  7. using System.Threading.Tasks;. x: x  H4 R7 e9 k  d2 h" I
  8. using System.Web;- O( a* r7 `  N  H; i  y2 u6 N. b
  9. using System.Web.WebSockets;" u7 D, n/ g4 G9 X

  10. ' D( l* Y1 t# l

  11.   H* D, J1 \2 L+ y3 C+ w% e* N
  12. namespace WebApplicationWebsocketHandler, {% [. Y6 v0 I0 X/ ^4 n1 R
  13. {/ d& D  O7 g- L2 E. z8 O
  14.     /// <summary>+ w/ ]) X2 J- `) e  y! K+ P' Z
  15.     /// 离线消息
    1 c- t8 ~/ |0 D0 [$ a- ^
  16.     /// </summary># C8 I  _1 C9 {' Y$ Y* m- T
  17.     public class MessageInfo" B! d; a6 x/ D+ P2 u
  18.     {
    4 N2 V2 `# ]- [. V" T
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    : j: |8 L. z, E" P6 v9 r
  20.         {
    ( C9 u) N9 x) ^5 z6 {( R  g6 L
  21.             MsgTime = _MsgTime;' d3 Y) [5 ~) G1 y! u
  22.             MsgContent = _MsgContent;9 q2 e  |5 E6 `
  23.         }1 j& A! B0 M7 I- n4 @7 L1 O1 @7 J
  24.         public DateTime MsgTime { get; set; }4 K7 C3 c. ]' t8 m$ S
  25.         public ArraySegment<byte> MsgContent { get; set; }6 H" w9 }8 d# k5 `4 l
  26.     }
    2 o. ~6 N: Z/ @" m' G! ]
  27. % [" r) F- i0 D, J: N8 l
  28. - I/ N: d' T/ p& F, g" ~: v. R

  29. + [& R1 x0 |+ e3 O- i: _$ s( e
  30. / {' s% `4 N" s3 r! _8 M/ h9 w" J
  31.     /// <summary>
    $ s  r0 Z+ a. |+ j6 X* D
  32.     /// Handler1 的摘要说明2 A  F) U' g1 d5 B6 t; D7 e# [+ V) W
  33.     /// </summary>
    4 x. X0 P3 Z  b
  34.     public class Handler1 : IHttpHandler
    7 A# Q/ ]( c# z$ d" Y
  35.     {
    / J& A& d/ V5 ?6 g
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    ! v8 Q: s3 R! r) K2 `
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池1 r7 K) B# V# Z) g: N
  38.         public void ProcessRequest(HttpContext context)
    6 c9 }1 T: P9 ?7 G6 ?6 Z9 b
  39.         {; r* B  f3 e% F: X) @
  40.             //context.Response.ContentType = "text/plain";4 n% g" D+ P$ a0 r9 y2 N
  41.             //context.Response.Write("Hello World");
    9 ?0 @1 C4 Y: {. x6 ?9 u
  42.             if (context.IsWebSocketRequest)
    ) b1 i) T& {" k* h
  43.             {6 }; a/ Q  I* u) c. R
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    # b+ \2 n# o- }5 c) ^
  45.             }
    * ~3 Q0 \: J0 q0 Y1 U3 b
  46.         }9 w" S- {1 K4 `8 l, h* v
  47. ! b7 Z3 S) V  I0 H
  48.         private async Task ProcessChat(AspNetWebSocketContext context)2 l% \  n9 K2 Q2 f& `& F& n7 C; ]
  49.         {
    4 c/ L  s9 Q, q2 {6 d3 i# J
  50.             WebSocket socket = context.WebSocket;
    4 R3 |* |( v. ?9 N) \/ w
  51.             string user = context.QueryString["user"].ToString();
    . a! H' N$ X' O2 T. n' g8 Z
  52. * n, ^8 z- J# }  T! y" Y% m! ^% Y
  53.             try
    0 d/ ?) p2 F3 d
  54.             {. X* N# S, [: C8 f: L$ a
  55.                 #region 用户添加连接池
    ( @: r) I1 r" |
  56.                 //第一次open时,添加到连接池中# n: \3 D+ y" ^8 v+ C$ p- G
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    4 B8 H9 Q9 x. y  F5 a
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加9 H$ u5 q$ {' g: K) y
  59.                 else6 @# [' V; J2 R2 h5 d/ l+ z  @/ k
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新! S% @, i- d3 J% t1 ]( V. T/ E
  61.                         CONNECT_POOL[user] = socket;
    2 K; ^2 U3 B/ t0 f& w
  62.                 #endregion9 j4 d( p* `$ ]3 G) B4 L/ H$ Q1 j

  63. ' ~, h8 l; T! x. Y( g) m6 P1 ?7 }
  64.                 #region 离线消息处理
    ) I6 i/ J6 r- O% _5 y3 w
  65.                 if (MESSAGE_POOL.ContainsKey(user))3 L1 c) |1 n, W  b
  66.                 {! N& U, @* Z( R. I0 {) Y
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    6 _, P5 U0 a0 d6 Z- h) r
  68.                     foreach (MessageInfo item in msgs)
    & _5 z: t% @! @) F
  69.                     {9 t: z5 C* z- I  ~! ^
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    / v6 `" D2 o. e; O6 j
  71.                     }9 ?9 w" Q7 }/ W+ H! K6 i/ D5 Y/ ]2 Q. N- z
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    4 s- z/ g0 J& o2 l
  73.                 }
    5 p: c; [( T5 e% w. a' ^5 F' T
  74.                 #endregion
    1 {6 n7 f4 D) S+ o$ O. P

  75. " `1 `8 X6 l, X# o& k
  76.                 string descUser = string.Empty;//目的用户
    ( {0 \  G4 D# s5 ^! L5 e
  77.                 while (true)/ q5 h' x3 o% K' z5 [
  78.                 {2 P5 N/ y2 r& E* S
  79.                     if (socket.State == WebSocketState.Open)
    6 |6 o2 K- o" M" t+ X, k5 P
  80.                     {2 V) X* F4 ~0 _0 r
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);; ^* n2 r, F6 i1 B7 ?! \3 `9 D
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);0 D1 [* S% q# T0 v- ?9 l

  83. # V9 O7 E% e2 m: u; z3 l
  84.                         #region 消息处理(字符截取、消息转发)( k$ l0 n5 z/ ^" ]8 p0 ~
  85.                         try
    7 N+ v2 f+ V3 F7 }* \6 W
  86.                         {
    8 j  A' J- ^0 E0 {$ A0 D6 L. I1 {
  87.                             #region 关闭Socket处理,删除连接池
    9 P# J$ W0 C" x+ S" c3 g
  88.                             if (socket.State != WebSocketState.Open)//连接关闭0 u( N: j. J( R+ c" Y/ ?
  89.                             {
    8 p3 n2 H; k0 e5 W# w
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池0 O* I* O% a. N2 U  C7 y5 |
  91.                                 break;
    8 |- T* V1 T" ~4 L
  92.                             }+ D6 ^, ]  u) R( `, E& z1 ^8 F
  93.                             #endregion. z# d* Z7 w* p! E1 Q

  94. 9 b& g' m1 N, z. z. Y
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息. J/ I! ^' b# p: S
  96.                             string[] msgList = userMsg.Split('|');
    0 [' q) w7 H# y
  97.                             if (msgList.Length == 2)7 u, l" q) j, O7 I
  98.                             {5 Q3 p. w$ U1 {
  99.                                 if (msgList[0].Trim().Length > 0)3 g3 I; N5 y, U/ m3 r0 B
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户; O+ C2 K) G0 {8 n  A6 F" a
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    / o! W: f9 ]  f. g% W2 [4 g9 Y
  102.                             }
    9 i* j9 I9 q+ z3 k+ B
  103.                             else- e' y, E/ N7 h- h2 s
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));5 T3 N) i2 v. s0 C

  105. * a! M! X6 t: {6 e% w4 t
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线' w+ g! Z8 t/ B' }
  107.                             {- [5 F* ]; Y7 q& Y
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端" @9 I- q) {6 f8 w
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    2 ^3 m, s6 p2 @) X3 Q- N1 i
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    ' L9 z/ B; a0 p) }+ q8 L
  111.                             }% F) W9 N( f- \7 K- O9 A
  112.                             else2 }# k8 \% i) t$ M0 H/ i
  113.                             {" Y- v) H6 I/ d6 U
  114.                                 Task.Run(() =>" B" `( Z3 J+ }3 g' R5 ^& R
  115.                                 {* _) N2 w, D4 S8 ?2 M( K* |7 ]+ X
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中9 y4 d# D3 e; ]* i( S
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());! _. G3 G7 y( Z& P* Z" P$ D
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息& z1 L+ u" d! O
  119.                                 });: Z7 |8 K; c. k
  120.                             }
      u4 H; w& y7 I8 y& S6 L
  121.                         }
    / ~, r: E7 t; d" B. h% u
  122.                         catch (Exception exs)
    # }& o# O# C4 q# v  p! j
  123.                         {
    + F, |; S: ]1 R; O0 r" _" c
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息  r8 S6 T# ~8 @- G* e+ D
  125.                         }
    * z( |) r. T# Z! R$ W+ @
  126.                         #endregion$ w3 d( L, F- Y' r* U5 z5 c3 X
  127.                     }+ \5 ]; c2 Q/ [2 G3 Y
  128.                     else3 O8 P) Z5 J7 R3 f4 n- u' _3 q
  129.                     {
    0 g/ I# @! ^4 q. B' K
  130.                         break;: [8 z7 L* S) [3 O  l, U) J
  131.                     }6 J( z1 R, E- L
  132.                 }//while end
    : T0 o$ A7 C% L7 t0 j) z# I
  133.             }% u' e( b" [4 m1 h( |
  134.             catch (Exception ex)0 k8 Z* P! j3 b$ ?
  135.             {3 o5 i  u, t2 Q
  136.                 //整体异常处理
    7 K) O  h/ Y8 S/ Q+ U: `  l
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    ) B+ `# o) T4 Q, f3 d
  138.             }, E" K2 J" e5 H; ~) c2 d3 g' `# g8 h
  139.         }
    7 U! }/ o' ?! i7 z! y
  140. 1 c' y: w4 |/ o3 Z
  141. 8 j+ T! l' o) y) u  U, n& F
  142.         public bool IsReusable
    3 y/ X; y. R$ v1 `
  143.         {
    4 V3 \- S2 `& l6 X8 n
  144.             get8 D- O6 J+ a: |" r/ A
  145.             {
    - V* x+ k7 e5 w
  146.                 return false;
    + K6 r8 g  c2 h, v3 r/ ^' }
  147.             }3 W$ M1 F8 p2 \7 O  `
  148.         }
    5 ?& V. M. k8 ~
  149.     }6 h3 D3 a9 h7 i
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
. T% e2 |' Q' B5 a7 }4 Z- M, W, [& Q





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