cncml手绘网

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

作者: admin    时间: 2018-11-7 00:43
标题: 在IIS上搭建WebSocket服务器(二)
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
  s7 D7 \4 d9 k4 A; Y% ?
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;6 u9 ^' [# R: V
  2. using System.Collections.Generic;
    0 C/ y, D, G$ V/ i) Q4 c6 i) a7 E
  3. using System.Linq;
    5 _, E3 j$ S5 e# d
  4. using System.Net.WebSockets;1 k! h2 A" C4 v5 ^6 z
  5. using System.Text;) s: S7 {, L2 E4 P8 f
  6. using System.Threading;4 b' r! N8 N' s$ w+ v4 W" d
  7. using System.Threading.Tasks;
    - D4 Z. x! p) j
  8. using System.Web;9 s# _. y* f- u# d* T9 z6 D
  9. using System.Web.WebSockets;  H. }9 e, H1 T7 s' i
  10. 4 C5 `0 J3 B/ K, D0 Z

  11. + C, }* ^6 r5 j1 p2 m+ E: c
  12. namespace WebApplicationWebsocketHandler# b, F' ^& x. u2 I+ D7 f
  13. {; g/ N9 g; `! f# r  N4 Q) q; x% E& v
  14.     /// <summary>
    ( W6 z- o, l& v- g4 @& e4 V, }
  15.     /// 离线消息$ s* Y5 o* f8 g+ E6 N6 t
  16.     /// </summary>4 ]5 G0 U# e: K2 C& q
  17.     public class MessageInfo
    - E, s* M3 c: w5 _
  18.     {! ?8 w" }' i% j& [2 ?" D3 f8 z+ J/ Q
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    ' j6 e7 ?( j6 a3 P% A  a) E
  20.         {1 \5 F# M9 |- u$ y& V8 W( b
  21.             MsgTime = _MsgTime;
    . s! t! U  L- X/ @  A. R4 z
  22.             MsgContent = _MsgContent;) x% T- N, T' Q& T3 l' ?: n
  23.         }
    2 m4 C7 _' v& v$ S  H( b/ V8 ^6 V
  24.         public DateTime MsgTime { get; set; }% J6 @" q# ^9 s7 a' G9 b" i7 y% Z, z
  25.         public ArraySegment<byte> MsgContent { get; set; }
    $ V, F& P: A7 K5 F1 ~8 i8 L
  26.     }* S9 Y" v4 E; N2 ^& @
  27. " f! y# r# z4 ^; a

  28. ; ?8 d8 e7 c" T% J; h7 i: R
  29. 9 v( S9 f6 O: C7 h, l' C/ o

  30. 9 W+ \2 G4 G$ d& r! a' u/ E+ X
  31.     /// <summary>; f$ Z# e% E0 g5 |9 }. B/ _; a
  32.     /// Handler1 的摘要说明. A4 h9 _2 n+ Y5 }
  33.     /// </summary>
    ) Q+ m1 C" t/ V- W6 f( S- [3 L
  34.     public class Handler1 : IHttpHandler
    " K. T* g5 ?3 }2 v, ~
  35.     {5 J/ E( l' K& @
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池9 x) b9 x4 t% D5 ~9 O* F. f
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    7 ?  V3 |( t& n/ C& o8 B
  38.         public void ProcessRequest(HttpContext context)2 d4 n+ S+ C% K
  39.         {. s( i3 R1 _. k
  40.             //context.Response.ContentType = "text/plain";
    ) l6 |; u7 ^+ }) _) G9 F
  41.             //context.Response.Write("Hello World");
    & O1 I+ G9 H. ?6 g2 }
  42.             if (context.IsWebSocketRequest)
    , T/ @2 p9 V7 u$ ]1 v
  43.             {! e5 z4 s" Z2 Q6 c7 `  S  b' A1 @
  44.                 context.AcceptWebSocketRequest(ProcessChat);  I4 Y. V5 H: m  B3 }
  45.             } 2 m" C# N  Y$ _8 k9 }# q% G& Y1 c
  46.         }7 S6 r' {6 y/ k. j+ z
  47. ) V! c0 p) ]: d/ R( O
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    , N. M# l; n. c2 t' }: q2 m
  49.         {* G; |' R/ s! f+ E/ [' I" q$ Q
  50.             WebSocket socket = context.WebSocket;
    ( F5 V2 v( ?  O% n4 {, }# m9 {
  51.             string user = context.QueryString["user"].ToString();4 M/ @) P8 ?& n! [
  52. " K5 A5 \+ Z4 Y( n8 y8 A- j) Z
  53.             try
    + C' ^' d7 a2 Y$ S; g& z
  54.             {% @, d8 ]) K$ n2 m8 @
  55.                 #region 用户添加连接池
    * Z8 e( E# r, P3 B* N
  56.                 //第一次open时,添加到连接池中
    ( c4 z; p7 Y( A1 j; n' G
  57.                 if (!CONNECT_POOL.ContainsKey(user))) Y  h4 z' c1 F
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加, K  f) z0 j3 g5 C. E7 ~
  59.                 else% M. B: C# V6 t0 z  P" h
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新! p+ B, {- g, o  I, {( Z* {
  61.                         CONNECT_POOL[user] = socket;; m. R/ C6 G9 Y
  62.                 #endregion/ M* i) @: y# T7 |$ A0 o8 b
  63. 8 S* k% Y/ q, `
  64.                 #region 离线消息处理
    0 \# m. B/ z! o. @  A- k
  65.                 if (MESSAGE_POOL.ContainsKey(user)), U8 m5 h5 I6 i8 Z3 t
  66.                 {
    # m- u7 G) C0 ~' g, B; |
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];: r8 b! L0 T/ M* N* q9 v  \( \
  68.                     foreach (MessageInfo item in msgs)1 Q- c3 z8 Y) H% G8 x$ M- h7 w) X
  69.                     {. Q6 e3 M' q4 S8 U' Y9 l
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    $ T6 C* z3 ]  _  R: Z
  71.                     }
    . U  y  F  J* h/ l
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息6 l: C5 ~2 _* ~# R, m  A
  73.                 }
    " d% E" U' }) P% C2 s. A/ T- a2 j0 f+ O
  74.                 #endregion( s3 y8 y: P% L2 \, Q
  75.   ]& E" e) ^2 h1 r3 l* j( d/ a
  76.                 string descUser = string.Empty;//目的用户6 h  j' p6 p  t- }: j; L" z
  77.                 while (true)
    # f4 P' v  F3 x' n3 v( b
  78.                 {' b4 O1 H" c3 [" B# [
  79.                     if (socket.State == WebSocketState.Open)
    / o) d  {9 s" r9 G7 t
  80.                     {
    8 x. e* x0 `- a' x# _
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    % ?1 `1 A' ~) m: C
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    # w3 O8 X0 R) @) b
  83. 4 N/ _. K, a5 m, y% l
  84.                         #region 消息处理(字符截取、消息转发)
      L2 P3 }4 J$ J4 o3 M
  85.                         try
    & f& R( T& h/ X
  86.                         {
    7 V3 W* \& s# I. V- V
  87.                             #region 关闭Socket处理,删除连接池
    4 L5 |7 m- V6 v/ h1 v( |4 Y: m
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    : V3 l7 s) E2 J5 B0 b5 M
  89.                             {  N; k# J6 L2 _
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    " Z/ s( H: n8 a# F% G0 [7 ~
  91.                                 break;
    0 A1 |5 _3 ]' c8 o3 M, v& ^
  92.                             }2 _/ @- ^3 ]- q0 z
  93.                             #endregion& x3 a$ k- y& S) ?2 D

  94. 9 ~7 w/ E) k! l2 D
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息( L: ?, [6 R" i: ?
  96.                             string[] msgList = userMsg.Split('|');
    & s$ m9 V2 m# ~1 r) B0 X
  97.                             if (msgList.Length == 2)1 G% F. N0 H2 n5 Q9 C! P
  98.                             {
    * A+ c( Q' m: u, d
  99.                                 if (msgList[0].Trim().Length > 0)3 A$ x' L3 k8 ?& S; G
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户3 \# c- G) l$ R' {3 A9 a
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));! l9 P/ J% ^! n! [8 A/ e1 A
  102.                             }
    ( V4 s, W9 [( @
  103.                             else
    7 A2 Z# l6 L* E1 h! H, {
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));3 M% S: H& ^7 w, d

  105. , R# f/ c: N! y! v$ I1 u& I
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线+ Y  V4 n* l; L) \2 Z
  107.                             {
    * y  V* K5 b( t$ M; C& i: e
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    2 J6 H, j( L$ X9 p, J6 V. k
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    8 \3 ]0 ^: m8 i* ^: ?8 Q9 z$ g7 A
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);, q( D. ^& q4 v0 y/ Y8 C
  111.                             }
    + J8 B; y5 Z) e9 q& A- _
  112.                             else
    5 s, W7 `4 t7 Y; q- g9 J
  113.                             {
    + N- N. U3 M8 |7 y: z
  114.                                 Task.Run(() =>
    ! x" q, C  W& C9 h( N0 y% ^  B6 S4 }
  115.                                 {
    - T5 `3 w' X4 [) \
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中8 f1 ?! u3 d9 a% g
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());7 b; p. u$ G7 A8 N7 h# l( Y
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息% Z( y5 t2 V* s$ ^# V" x! M
  119.                                 });
    3 g' n( B+ d: R) |
  120.                             }
    * Y& W; G5 v# t8 ~. z4 C, U4 I
  121.                         }
    1 y. C( Z' ^, s, ]1 r3 w
  122.                         catch (Exception exs)% z+ U% f3 J2 z. ]6 z9 o
  123.                         {8 I) W6 ~/ R: ]6 y$ N
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    4 t3 W. m( G1 C  O
  125.                         }
    2 k" R) n2 `& S! n% C' M
  126.                         #endregion
    ) m3 A& a$ p# M4 u% Z
  127.                     }
    $ z# u. `9 X4 z. W7 K
  128.                     else9 I% x) c2 l& a( z3 A! |
  129.                     {- \6 O4 p$ Z2 q& X
  130.                         break;
    / R- i7 z% r4 r) ~' }! [
  131.                     }% f/ i& a( `2 {5 e+ H$ P, ]. v8 C0 D
  132.                 }//while end
    # f( B2 s* F# B: R
  133.             }+ Q( A+ @8 G# e+ _* i
  134.             catch (Exception ex)
    5 t! C( i; [" p5 \+ R( M
  135.             {, M( F( h, e) j/ z1 u& N9 s
  136.                 //整体异常处理
    ; [8 `0 |9 b9 f/ e+ ^; |* P6 y4 R
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    , h* a  ?; \/ F6 e0 _' C
  138.             }7 s2 `7 p; R' V
  139.         }( p/ ?  t4 ?  g6 B
  140. 3 \: R. w) \$ J3 b
  141. & U  {* I6 R; I
  142.         public bool IsReusable
    6 Z  Z- r7 V# [5 z. V" u! U
  143.         {
    6 G& U, B1 I" r0 S4 l+ E, m
  144.             get
    ' u  p  Q8 e2 X/ O
  145.             {4 z+ R" `. g2 n7 Z" e' J# a! T
  146.                 return false;
    # M: p3 F2 m5 G$ Z' t
  147.             }, m* M7 d$ O6 n. }
  148.         }
      c% F/ h0 ~- R1 G# y
  149.     }
    & z! F8 X: s4 Z! ]; r9 G" i
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

  B" ^  J) y2 }1 p) K9 S




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