cncml手绘网

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

作者: admin    时间: 2018-11-7 00:43
标题: 在IIS上搭建WebSocket服务器(二)
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
+ f0 ]4 F( F& C8 {3 l) ?6 N
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    8 v1 o+ V: c. ?$ u) `, w
  2. using System.Collections.Generic;% W% T6 g. I+ D8 N6 q( y
  3. using System.Linq;3 A& N! h6 L4 ~5 B2 r
  4. using System.Net.WebSockets;7 }; o/ }  r9 ^% Q. w$ n% E
  5. using System.Text;
    ) r& T* J8 w8 Q
  6. using System.Threading;
    ( U7 g! U0 `: h1 A  s7 n
  7. using System.Threading.Tasks;
    ' p. ~5 f& X+ F& K8 m
  8. using System.Web;# ]( f2 ~  W$ z0 j0 T
  9. using System.Web.WebSockets;0 E% i5 T6 T5 P, y: u6 s

  10. " {1 c# x/ ?' `" X
  11. 3 t- w. Y5 g0 {% C" C7 ~
  12. namespace WebApplicationWebsocketHandler' ~+ R7 C7 J; \: h5 f5 Y2 e
  13. {
    9 Z' H0 ~/ C/ w7 y; h; l
  14.     /// <summary>6 Y; ~' Z" g9 o* E$ f: r. ^
  15.     /// 离线消息0 R4 o3 T, a+ g; S4 H( c4 X9 q% c
  16.     /// </summary>
    + \) m! z8 Q/ l# ~
  17.     public class MessageInfo  e( A' v% q1 R- J# b: m
  18.     {8 {" P# M' G4 B( F# a( ]: M# J0 s
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)$ I, a# v( C& |& `, w- O
  20.         {: e! F/ _& i% {
  21.             MsgTime = _MsgTime;
    2 K" a2 e7 L0 F7 a
  22.             MsgContent = _MsgContent;
    6 S% \. f7 r2 g+ \/ ]
  23.         }
    / n; X; Z' V5 J
  24.         public DateTime MsgTime { get; set; }
    : {/ j. L/ g: E6 ~) F7 e4 ?
  25.         public ArraySegment<byte> MsgContent { get; set; }
    . M: ]* K" B5 }  W( w
  26.     }6 s2 ]( K+ `( k! |' `

  27. ( D& }4 G5 i8 }

  28. 1 F+ [& r; h, H9 {* I6 [9 i2 T
  29. : r! l' y% C7 R

  30. 6 @* Q# D  |  j# t: l0 H( m- p' S
  31.     /// <summary>) E+ P. o( n% J$ p( n
  32.     /// Handler1 的摘要说明. h! q0 U! U- ?7 Y+ a# \$ A
  33.     /// </summary>, j2 R! t# X- a$ z4 K  y- A; j
  34.     public class Handler1 : IHttpHandler
    ; w& r1 ]$ V4 V9 g" y$ R9 q
  35.     {
    % j! `' W0 h' I
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    : ]; N1 J2 H4 k) K( x
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    ) j' O- T& N1 l9 F8 R  V
  38.         public void ProcessRequest(HttpContext context)
      d" \+ I' Q4 e! E$ z5 N2 h6 Q3 l- H
  39.         {
    * I1 `& R8 S( c5 T& g- d6 _. P
  40.             //context.Response.ContentType = "text/plain";+ A0 A$ G6 l- n0 y
  41.             //context.Response.Write("Hello World");3 z* o6 o. n! u7 F! X) Z8 W
  42.             if (context.IsWebSocketRequest)' z8 K* h2 K/ t/ e5 v
  43.             {/ }0 G7 S7 N. W) z8 G- h6 O) O
  44.                 context.AcceptWebSocketRequest(ProcessChat);3 M5 J0 ~4 ~4 t& \1 i- f
  45.             }
    5 c- c- y5 p4 s3 p, @
  46.         }$ D% f/ s* n' p* n

  47. # ~4 W1 i2 k7 _# `. F
  48.         private async Task ProcessChat(AspNetWebSocketContext context). f7 M8 ^+ B- |" f7 w
  49.         {$ L% ~# Q# b: I7 C0 p0 l
  50.             WebSocket socket = context.WebSocket;
    . |: ~1 Z+ Y0 D8 ?- o7 J2 Z
  51.             string user = context.QueryString["user"].ToString();! [( A) r# \! u* |0 q& ^1 w

  52. ' B$ T  s* [3 J0 A* D
  53.             try
    ) c5 n5 J1 v* g; U. Y
  54.             {
    " I( n( k% p8 j
  55.                 #region 用户添加连接池4 h/ k7 {. u6 ?/ m
  56.                 //第一次open时,添加到连接池中
    6 a5 J) D; [! V. D1 `
  57.                 if (!CONNECT_POOL.ContainsKey(user))2 P0 {' D9 R0 W
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    ( l* ^% u: ?; |7 k
  59.                 else
    7 K3 {+ d# l- G+ Z1 E5 R
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新' o/ a6 n* |! w  @
  61.                         CONNECT_POOL[user] = socket;
    8 S# D+ U- x2 G% c0 u+ v
  62.                 #endregion8 d- N/ e8 y# @# X
  63. ) V* Q$ s8 H( l' Q6 ^
  64.                 #region 离线消息处理. e1 G7 k( G  x$ e4 h9 u) `
  65.                 if (MESSAGE_POOL.ContainsKey(user))) l; \  l+ O) d* N/ r) P/ k
  66.                 {8 p$ J2 a3 Y3 I7 y: _+ \$ D% E
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];5 P7 s& E5 C: d
  68.                     foreach (MessageInfo item in msgs)
    8 @, y9 s6 f8 U& v" t
  69.                     {
    " J, h: H: o7 Y! @8 n7 i
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);/ h  t6 A! s4 M( [% p/ L% I* |
  71.                     }/ ~3 Z& q) n! h1 u5 t) P
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    : l: I; e6 X7 N& o& x
  73.                 }$ ], G5 V1 y# I) T5 u% k' d: I
  74.                 #endregion1 K  H' N/ H9 k$ N! e+ k: K% W* W2 h
  75. 4 k  K3 W2 i5 b* K" z
  76.                 string descUser = string.Empty;//目的用户
    0 x3 W; o$ O% K  a) ]1 t; C
  77.                 while (true)& y. u# S( u  g: W+ l  O) X6 V
  78.                 {. U7 t" P' g( r7 {. ~8 p
  79.                     if (socket.State == WebSocketState.Open)
    / J$ Z) C6 g8 w
  80.                     {9 ^; n+ H# {  p
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    " H: t. K* |- a/ x8 n
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);: o1 c0 X( t$ d- g5 D
  83. ! A8 d6 ^6 `) I. {2 m7 e( E$ Q
  84.                         #region 消息处理(字符截取、消息转发)
    . l! |5 H, C. Q4 j
  85.                         try  U6 d+ l2 N; {" U4 s+ \/ K# s
  86.                         {
    # U+ s( V, [( i
  87.                             #region 关闭Socket处理,删除连接池
    4 X/ Q* d' i# r
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    - I- Y! i% ]+ M: ]% o
  89.                             {6 x2 X4 w" O3 ?- T% r' ?( s4 n
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池2 J! R) O/ A1 S( ?- v  e& J$ a6 `! j% T
  91.                                 break;
    ) C4 ], s+ ^! U" H+ ~
  92.                             }
    2 o% r! c$ E5 x) p( f3 f6 ]
  93.                             #endregion  l# `" x$ Z5 `$ T

  94. $ k7 z1 U3 t& C1 N: z$ e- t  \
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息; q' U1 m" N$ t8 G4 ^9 E/ P
  96.                             string[] msgList = userMsg.Split('|');
    1 t4 E  N6 w# z1 c3 j. m4 v4 @
  97.                             if (msgList.Length == 2)* O& Z; R8 \; A# o- p& F
  98.                             {0 s2 Q' T2 Q, |
  99.                                 if (msgList[0].Trim().Length > 0)
    5 a" i. l/ ]& k" T) k
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    9 S' b* S" o- S
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));8 E% r  Q9 p+ L, B# o, J; Z
  102.                             }
    * q6 ^$ `! i" b! n8 j; W1 _
  103.                             else
    1 i3 z6 T5 Z& m# Z: m! i: }: H% S
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    # P; K2 [+ A, M  f
  105. / X6 ?0 L: }+ s' G
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线0 w! w) o" |6 g/ I9 X  |) `
  107.                             {6 L% e' I* ?2 N8 ?  ~$ u1 A
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端2 g+ j1 j4 W8 u1 q- O* i7 i
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    % D$ e6 k- T* `& Q+ k
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    . V5 V" n* [" c1 y/ g
  111.                             }4 O- w  f6 P5 p! X0 o' @" x
  112.                             else
    : u# f2 j; F" J) Z3 o1 V$ t
  113.                             {8 @" M9 l; a2 g% s
  114.                                 Task.Run(() =>, ?4 T& F: J- ?- j: L% X, a1 F; K- }: M! l" m
  115.                                 {
    . U. G9 O+ B7 ]8 }5 }) ^4 G( S1 R
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    0 N' P; {% d9 A) v' ?& s
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());+ H) Y  B5 B2 ^0 \
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    : H( E7 z9 e* W6 W4 c1 v- @4 b6 v1 q
  119.                                 });
    . c0 }7 q( e( `8 A* z- M! j
  120.                             }
    5 ?' q+ K. L/ m3 k5 ~, t6 @
  121.                         }3 I! w1 C/ L9 }4 z
  122.                         catch (Exception exs)0 \4 ]/ Q" e# [/ N
  123.                         {( G# z5 ?) J$ H: x2 Y! b* j4 @
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息% n5 Q- d7 y' R3 |6 M: f$ e# Z
  125.                         }& m+ K, i, m! J: [* D9 K
  126.                         #endregion  `& P" K5 P3 J. J& e& X  B
  127.                     }) @6 S7 }) u/ g( ~
  128.                     else
    & ?/ ]4 Q9 A5 D2 d. x+ R9 }
  129.                     {5 r, W5 `+ j0 J  _9 A9 [+ a. V
  130.                         break;; h) O% S7 h5 s; J1 I) [( d9 z6 T
  131.                     }. c  g5 t$ h0 x, J; L7 G. z
  132.                 }//while end3 v# g' `* w! j3 v$ G0 o+ [0 b
  133.             }
    & P; @- C+ b; s* }( k
  134.             catch (Exception ex). f- C! Y8 x/ W- G. P1 u
  135.             {
    & a/ S  |% k* a+ H
  136.                 //整体异常处理
    & `9 H& P( W, }5 a; |, u
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);. F8 ]2 X7 A7 j; N$ @1 E
  138.             }
    , l0 w- |7 n3 p8 l" ?- P
  139.         }
    $ A0 I- k7 u% G) \! p
  140. 9 r, ~( f1 r/ V( A2 `
  141. ! E. D; @, D  k
  142.         public bool IsReusable: d0 _+ @) p7 c3 \. g" O7 ^* y8 M
  143.         {
    ! Z- d- S. T8 O1 X: f
  144.             get
    4 R7 E: d2 v6 `& C  k3 O& A8 C, I6 ^
  145.             {' L5 W9 K5 ~0 q! D
  146.                 return false;  F& j; o+ w* L4 ^# A
  147.             }* i( F, @/ |3 J& e- j
  148.         }' ^; Q, H8 e+ v$ S( j! [
  149.     }
    7 t! m+ \8 f4 ^/ A+ M9 z
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
+ C% z- J* A) g- P/ h' a6 K





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