cncml手绘网

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

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

1 P, M; _) l" {6 X( I
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;" u* `* H- q! m) K( |
  2. using System.Collections.Generic;1 H- }+ w3 B- a# I* `
  3. using System.Linq;6 h+ ]. q+ ^! M
  4. using System.Net.WebSockets;
    2 x4 k3 M7 |9 `" l
  5. using System.Text;
    7 A" _; b" s1 ?1 _
  6. using System.Threading;
    ( Y, N1 Q9 z1 e/ @
  7. using System.Threading.Tasks;, x. \9 O" i0 |+ _0 s
  8. using System.Web;
      [" ~; x* F$ L) \
  9. using System.Web.WebSockets;
    " Q/ I2 d/ A# \
  10. % D4 f) M! W" w! ]1 n9 R  J- G
  11. / w/ }" T$ I' H! Z$ W- N
  12. namespace WebApplicationWebsocketHandler
    9 q2 [( U( c0 H4 L$ j/ h
  13. {& @! }4 Z2 a4 N* W% g( m
  14.     /// <summary>
    * R2 E$ C1 Y0 _0 D
  15.     /// 离线消息
    4 j% G6 _( k  [% Z5 a/ x
  16.     /// </summary>) Z  G# P7 e9 n; h* W* O
  17.     public class MessageInfo
    ) T5 [1 w9 `" P
  18.     {( ]$ v3 n2 w9 y* C: e
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent). W" }; ~0 b0 G3 f, \- _( a
  20.         {
    . p7 X! a) O8 Y: X- F% Z
  21.             MsgTime = _MsgTime;3 l- Q* S5 z9 n2 _& y
  22.             MsgContent = _MsgContent;
    / p9 j- y9 A* E; O& a( S! v
  23.         }
    " g7 `) j; z  U3 ?& Q- W
  24.         public DateTime MsgTime { get; set; }
    ! I6 h6 D4 b( v; O
  25.         public ArraySegment<byte> MsgContent { get; set; }
    ) |5 k, y. V& G4 p
  26.     }
      n+ n; a% r) E0 A& x4 T

  27. ( @4 {9 l& B5 s- A$ j6 E) J
  28. ; t; H6 V2 ~7 J; r: y
  29. 1 g- Q$ p& S) }( Z( b- ?8 S

  30. / Z7 }. K+ |8 u0 L
  31.     /// <summary>5 R, P$ S) v6 l, L7 x
  32.     /// Handler1 的摘要说明
    9 {1 c& U& ]. P9 r" K# r. ~, O7 @
  33.     /// </summary>
    + d& k( k7 @, W: e% g( j
  34.     public class Handler1 : IHttpHandler
    $ E5 r5 ?' s' k  U) `5 V/ p' ?
  35.     {( S/ b  p/ N+ W8 W$ K6 M$ p, e
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池2 B- @$ a  S; w1 f
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池" B* a, B4 {4 s" X
  38.         public void ProcessRequest(HttpContext context)" N' n, ]  e' r' T* ^7 A
  39.         {( h( J5 y, i6 b( q5 Y% U6 C
  40.             //context.Response.ContentType = "text/plain";, @6 ~3 J- w& E: D
  41.             //context.Response.Write("Hello World");7 e% L- x, a# {3 o" s! J
  42.             if (context.IsWebSocketRequest)( F, ?5 Y9 q9 R1 a
  43.             {
    ' q' H' e; E0 B; e7 A
  44.                 context.AcceptWebSocketRequest(ProcessChat);- d; t/ ~$ W6 u9 ?/ C6 B
  45.             } * }8 d  V' S' F8 B: T+ j
  46.         }
    * W6 D+ Q1 {) l: b) ~3 t

  47. ; p! n' S' Y& e5 L7 r7 o
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    , j- ~/ p' r/ F% Q5 ^
  49.         {
    / I4 @$ f5 l, `2 {
  50.             WebSocket socket = context.WebSocket;* d. c" E5 u3 v, k3 ~) d7 O6 V
  51.             string user = context.QueryString["user"].ToString();1 L) k1 o) I! K
  52. * D0 @' D6 \  M2 {: \8 r& F6 r- ?
  53.             try" r! s* S# g8 M1 G
  54.             {% e% L+ _6 w+ [( |, _1 r
  55.                 #region 用户添加连接池4 p; H9 ^) z; j' b+ {* u# F* i5 j3 }7 b
  56.                 //第一次open时,添加到连接池中
    6 T$ Q; _5 N0 N9 ^4 U) J5 ?2 s
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    5 j: k4 n+ F6 S* x' H, T
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加( A" D( i9 A: B9 a$ f
  59.                 else
    ) B$ a* c& M4 T
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    : Q3 l* i' o$ k% ~7 c7 T
  61.                         CONNECT_POOL[user] = socket;3 k+ G+ ?; w: Y7 ]+ l  t
  62.                 #endregion4 i! b) D; [& H0 T. y

  63. ; z/ i  E; ~3 b9 Z1 s+ {
  64.                 #region 离线消息处理$ Y0 j1 Z# Q* c9 l; E
  65.                 if (MESSAGE_POOL.ContainsKey(user))! q0 J+ L5 F; j6 J3 C
  66.                 {) L1 r9 o" G3 u! i
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];4 o+ _( Q8 T7 r3 _0 O. j1 D' o6 ?5 {$ T) ]
  68.                     foreach (MessageInfo item in msgs)
    9 n/ R( w+ C6 V6 ]& ?9 J7 S
  69.                     {' t+ N9 T# \" y* H
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);$ @, Q" ]2 m4 g9 F$ T
  71.                     }4 M6 d$ v' F* \8 m
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    & n! ~" i( k, s2 A# y
  73.                 }0 l3 u( T% ~3 N$ {
  74.                 #endregion5 c+ \6 q7 w, @% w& n. z. }
  75. 7 y/ _7 t* r8 j5 t/ k' l6 `" Q
  76.                 string descUser = string.Empty;//目的用户
    2 Y' d' \& [$ M0 o
  77.                 while (true)8 l( p' U( W3 y6 h. T. D. ?; U0 u7 W; q
  78.                 {
    ) z# e' Q# {3 M8 r% C  m
  79.                     if (socket.State == WebSocketState.Open)+ w! G4 x3 A. M+ k
  80.                     {9 Q- E) g  q: _8 M3 O
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);3 H. S7 h: }& S* k; s1 t
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    " f1 l& t# J/ U
  83. , ?# z! |3 |- _; J. y) I7 p  h
  84.                         #region 消息处理(字符截取、消息转发)% z" s, K/ ?: J9 r2 _9 i
  85.                         try
    % a; ?+ @+ M' X* @6 Y  t7 [1 y
  86.                         {( U$ J' U' T. b% R
  87.                             #region 关闭Socket处理,删除连接池1 Z! @4 J2 d3 @/ T. k# L! o
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    ' k# c, D) t; D, h# \
  89.                             {5 f' l7 a- ]2 _
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    7 J1 e: E) T. L% q
  91.                                 break;
    2 m% ^0 r" ^7 u4 C
  92.                             }
    * [6 O& E" R6 E5 Z) R  d
  93.                             #endregion) j% q+ p/ b2 N3 O1 D
  94. * Z, L- t+ j3 e7 Z" h+ A: _3 g
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    & S# A( I9 T% y3 @4 g0 z+ @
  96.                             string[] msgList = userMsg.Split('|');
    / C1 D6 ?9 A- v# K/ ?6 x; p# w! {' [
  97.                             if (msgList.Length == 2)3 ~: n: S3 v, W; G) E% P- w, k( }
  98.                             {
    / g% h7 R* Y6 L$ Y/ c$ g* s0 o+ B7 w+ c
  99.                                 if (msgList[0].Trim().Length > 0)
    1 n6 N, H! b3 q
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    5 t/ r2 R- l7 p9 T4 ^1 Q3 O: o! F
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));: d1 ?& @; t' d
  102.                             }  i: T: N% u: r% P% W$ X, x0 A# Y
  103.                             else* e% S  G  U( o8 p$ a) [9 f
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    2 s/ H1 L2 h! p8 U: e! C; }

  105. # f! O5 A) z/ e" Y  P% @
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线; e  w" c% R5 @& C
  107.                             {
    ! S) P7 o3 V4 v( M9 W6 g$ m
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端$ }. Q) ~- Q( e
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)+ T& m' }: z" j. ^' G) G2 ?
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);7 Y9 {* W# P8 B6 k
  111.                             }- x9 L* {+ |& j9 g* j; N) o
  112.                             else' J8 h. ^1 q( x
  113.                             {+ @( q( c1 t& j" j5 N
  114.                                 Task.Run(() =>
    . \+ N( F* p: I0 r$ A3 X- K
  115.                                 {
    : Y$ n% q& y8 X5 R# B: J7 y
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    7 Z3 f6 ^# T2 P3 a, Y7 c9 l1 h
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    7 W! c+ @  G0 }1 ?+ C' V1 v
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    9 X2 v9 S% R! e+ L
  119.                                 });
    3 M6 B# T0 e# z; I) `! S
  120.                             }. T( E. Y, o; U) P3 s* {2 @0 u
  121.                         }! ?1 e2 r+ V) t" B" Y2 ~
  122.                         catch (Exception exs)
    6 e" D2 k' ^5 N$ J5 _
  123.                         {8 `1 |( E% [2 e/ l" _
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    - `* \4 L9 r2 ]
  125.                         }3 p! f, y7 n) C+ N2 l' ~
  126.                         #endregion
    . _. D# T) @% ^: z$ i1 q
  127.                     }
    . Z/ \, d% j, c+ q9 W. u4 d& L! _0 q! j
  128.                     else2 |: Z% R. f: `/ N. ?( v
  129.                     {: v9 t/ u; n* j$ K
  130.                         break;1 [7 [( y! @: l+ L0 F% R/ P+ c
  131.                     }
    , y( [+ }2 z0 b! u/ k
  132.                 }//while end7 f) K. L4 k8 O
  133.             }1 D* o$ F' J. H# A/ H
  134.             catch (Exception ex)
    ' }% i$ A- _; A
  135.             {- V$ Y5 }  K9 n5 n
  136.                 //整体异常处理/ [0 T: L) N- ]$ C
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);6 y" j. u4 Q) W* G
  138.             }
    , q4 A$ r3 }6 _' n
  139.         }- m: @: d8 \7 L8 @4 j0 P

  140. 4 A8 |+ w0 Q+ f' F
  141. * ?; H2 s7 X0 _. c1 v( k
  142.         public bool IsReusable
    & v% T5 k9 E1 V5 n. c
  143.         {& R% k- s& Q' C  c8 Q' j! f: V
  144.             get; C8 W% Q$ o6 Q7 f+ p0 B
  145.             {3 W1 o) d5 j! I5 v
  146.                 return false;
    ! c- ?1 [+ f! t! T- Y/ G2 ^; G
  147.             }
    " ?# M" K# ?5 j+ Z) M+ `9 I2 l
  148.         }
    5 |$ i9 h4 m+ V  T; w
  149.     }( q6 e3 y* a* ^8 c" g3 L
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
- ?# T% z( `+ z2 o% @% x& }  g( g  ~& }





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