cncml手绘网

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

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

! _3 [: `6 V  b7 x
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    9 _+ O! y0 v: |* x! O  c
  2. using System.Collections.Generic;
    3 C$ B3 y. R8 s
  3. using System.Linq;
    5 S; B6 S/ B, Q" _8 f8 P
  4. using System.Net.WebSockets;
    + B. V1 W( f+ \. P
  5. using System.Text;; s3 J9 A2 g% w5 L6 i6 v
  6. using System.Threading;$ U1 `1 s! J2 a- R. q
  7. using System.Threading.Tasks;
    / r* N" b- E8 a8 A; A- U1 {
  8. using System.Web;
      T1 P  X" F( ~7 x0 P
  9. using System.Web.WebSockets;; _: g" L7 M+ H* c% y
  10. 3 Q: F( P' G( J- Z, o+ S
  11. 3 U' u5 p: _6 a) W% X
  12. namespace WebApplicationWebsocketHandler+ L1 r1 [  m* e4 w
  13. {
    0 U% o2 V( x! e3 l
  14.     /// <summary>
    7 @; ^8 J; T( z: m  v; J+ n
  15.     /// 离线消息, I- A! l7 }5 @4 C1 i& `4 [* T/ R
  16.     /// </summary>% \% h& B6 W. ~$ t* R9 g4 Q" ?
  17.     public class MessageInfo; m+ o# `# ~4 I3 B9 a" e
  18.     {
    * o1 \! B' d$ U" o4 O4 C
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    0 O( D' d. l; O( Y8 p5 Z
  20.         {" L8 U" Q5 B8 ?
  21.             MsgTime = _MsgTime;& S0 v+ R- `' r$ O4 t" Y* h
  22.             MsgContent = _MsgContent;( _* ~$ |7 I+ J$ q* X" C4 @
  23.         }
    % Q8 T! ]6 v$ }9 t$ `" I
  24.         public DateTime MsgTime { get; set; }
    " N( k6 H: Z6 f4 ^0 {
  25.         public ArraySegment<byte> MsgContent { get; set; }( \, d" }9 w, c' [7 v2 L
  26.     }
    7 T# a4 a' h: d: l3 e! @

  27. , r: O9 s  M$ T! r

  28. 9 B# P5 B9 H4 x4 `" m- G& E. I$ e

  29. , n& i! o( P0 w2 u% a
  30. 6 L" `7 T7 R9 K: m6 f2 t& v1 u
  31.     /// <summary>
    + [% E0 B2 ?+ {" v& F
  32.     /// Handler1 的摘要说明
      G1 p: M" O: u/ n3 d$ z  F
  33.     /// </summary>
      s3 ^! n/ h2 G9 J1 [2 {8 x: n
  34.     public class Handler1 : IHttpHandler
    : ?; x( T4 W8 w
  35.     {- y0 J3 C8 Q; V
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池9 W; K; W3 g5 f2 {+ j7 q4 V: _" E0 O; B
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    ; r/ |, A/ p1 R3 T/ o/ {4 `% Q
  38.         public void ProcessRequest(HttpContext context)
    + {: _- \$ y3 I/ x( K5 Z; y
  39.         {- S' R8 r# ~( d; u, X
  40.             //context.Response.ContentType = "text/plain";
    2 j! l& O, I6 v/ e1 S, J
  41.             //context.Response.Write("Hello World");
    4 Z5 l) l, E5 B* R' j5 g
  42.             if (context.IsWebSocketRequest)
      w; U6 G5 m) E% H
  43.             {. y8 H0 d5 f7 ^8 g: o
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    / D; ]4 v: [! l+ D- A8 B; {
  45.             } ' [5 k8 ^/ {' x
  46.         }+ E! G- S/ v1 t! v
  47. / ]+ }& D$ J' f0 f3 _
  48.         private async Task ProcessChat(AspNetWebSocketContext context)) [1 I. M6 G' s) [, O. t: ^  a
  49.         {
    ; `/ a; {- P4 G, @1 @
  50.             WebSocket socket = context.WebSocket;
    + B5 x9 ?" w6 [$ F" H8 m6 |1 N: h
  51.             string user = context.QueryString["user"].ToString();. G3 L1 c% @! X% F" U; }

  52. ; `: u. U! v0 J7 W$ _
  53.             try( `4 N9 \- a$ R3 v/ @/ {
  54.             {
    : R) `: v0 Q" _* q4 m" W- J$ ]' {
  55.                 #region 用户添加连接池2 i* l/ n8 V3 \3 j. p3 }0 }
  56.                 //第一次open时,添加到连接池中" b" }1 }* G' @# y
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    . F* c9 e7 _; h! l
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加6 ^! c( I3 _& c& E
  59.                 else# A; B: _6 K- `0 G2 b
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新' J1 v+ j/ m* U/ I/ H3 [
  61.                         CONNECT_POOL[user] = socket;
    . \7 x5 _" \8 W+ U1 L, b: h, r
  62.                 #endregion: I' g4 z7 A) p0 s0 a4 x
  63. 3 t; o7 X/ R& e6 G- f/ R% L' k
  64.                 #region 离线消息处理- l) y1 m) y# d
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    7 R8 j3 S( j' G; X
  66.                 {
    9 c/ A% g! e; J' O( P! Y
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    # ~7 m7 Q+ J9 X/ w
  68.                     foreach (MessageInfo item in msgs)
    & V$ l' C( B8 m' L; p4 K
  69.                     {
    5 t. r6 l9 F: \' z& u' p
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
      I; N. G: f* K. _5 ]; f
  71.                     }
    / d; z) H) q% L3 I% F$ ^: O: v% v2 g
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    2 m7 ]+ h# c7 @
  73.                 }. A5 p. j& }. e) T: n
  74.                 #endregion
    : L4 J8 k0 L$ G& Z5 M9 u/ P

  75. ' g. N7 c, P4 R, |- d
  76.                 string descUser = string.Empty;//目的用户  }2 |' F9 a; y1 w5 M
  77.                 while (true)
    9 G! @3 q$ k1 Y# v6 A" E  s; J$ ]
  78.                 {
    6 P7 }% G/ C# G
  79.                     if (socket.State == WebSocketState.Open)" [' P# m0 `  _( R$ V+ |
  80.                     {
    6 ~* @0 b" {* G% I+ {) A
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    & V8 E0 l% b9 Z6 c! o2 e4 A
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    , ], x7 L0 `1 L3 X
  83. 4 A' H' g. ^" y+ y
  84.                         #region 消息处理(字符截取、消息转发)  s; e" r- j, ^8 g- }7 p
  85.                         try2 n4 ?" |& l+ E+ Y: b
  86.                         {5 A0 Q( ?4 Z& J& e
  87.                             #region 关闭Socket处理,删除连接池! A- i  y  l6 J9 w- s
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    $ `; e/ i( O3 k' u' \' L
  89.                             {
    ( {0 f1 C- `1 [: Z$ n) T
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    - O$ F4 c( j/ I' v
  91.                                 break;4 @( M" U; R4 P  A" q" ^
  92.                             }" Q2 A/ Y- C6 y( k  O$ |7 ^9 F& ?8 u
  93.                             #endregion
    ) L! s! Z; L. ~( u. P: K3 Y
  94. 2 b! {  F% I6 {: t) V0 d
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    # {1 i, M  T( Q2 A+ M/ y
  96.                             string[] msgList = userMsg.Split('|');! }! s- r; n& o  m8 F, t9 m
  97.                             if (msgList.Length == 2)
    . O* j1 c6 B' q6 y: z* O
  98.                             {; I/ h, o2 b) H6 I6 K" P
  99.                                 if (msgList[0].Trim().Length > 0)
    ) i( X. o" ~" y5 J
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户" ?1 L2 Z# i" }2 a/ D2 w
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));* }* l9 W- e% v" ~
  102.                             }
    & D$ h( |# p# o- E! e, f5 x+ [7 }
  103.                             else6 ~- O; b. R  [
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    : Y' i6 ?2 \$ \" [. e6 @9 _

  105. 0 l4 X; R( L- q8 O- s& M+ b
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    % d6 I, V+ T, N- ?
  107.                             {
    * J. x& H; {0 O- E4 l8 r/ E
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端- ~5 Y6 _0 Z; \8 i) ?; f
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)- c& w; S1 O, \& Y) `4 _
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);% Q+ k4 t$ y9 {. m
  111.                             }
    " s9 ?+ N! d5 G( J6 `! p
  112.                             else
    & b8 W! S  Z, H' {3 N7 y' g6 g
  113.                             {
    0 A* @% W2 i% D5 z0 |
  114.                                 Task.Run(() =>% ~$ I- a% k0 C  r4 w( V. I% p) F8 T
  115.                                 {
    " f$ ~# [* i- D9 e9 V& F
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    # W/ ^9 X2 {. H- [
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    2 r; v9 }) `9 _
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    / C0 S3 h4 \6 a+ ?
  119.                                 });
    ) p$ r( l3 Z& @: R( n
  120.                             }& P; Y+ I0 b7 S) u3 R3 \! v5 z) {9 W
  121.                         }7 F8 S; W/ n/ K( D$ C4 C( }( p
  122.                         catch (Exception exs)/ e: h  P$ K; f. ]
  123.                         {
    . ^; l4 _& |6 U; B8 M
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息" ?! o2 @' H8 m, r2 R- v
  125.                         }2 u* ?7 y/ l% r4 z( R# j' M
  126.                         #endregion
    : y& O; [3 ~5 `# ^6 D* b6 q
  127.                     }
    4 h2 D: N4 r$ y1 e
  128.                     else4 E' z+ {) m7 b8 E6 y- B, J, q
  129.                     {
    ( p/ S/ N2 h  @5 e. Y5 x% G
  130.                         break;9 Y3 [; n( A# U( C* L9 a# g5 q
  131.                     }" ?+ L4 z6 o9 v  ^; H' R6 {7 }
  132.                 }//while end; y/ f1 h8 S+ c. B
  133.             }4 e; d" z3 K  Y& J  d* k
  134.             catch (Exception ex)1 Z3 C  i' r6 ]' v% a* x
  135.             {6 J6 |3 A+ u. L9 f
  136.                 //整体异常处理
    4 q6 P, L" p5 t
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    6 g& G, e& ~5 G/ n( h* |
  138.             }
    ; _- b' g" Y& ?$ {  @4 F; K
  139.         }# ~" o3 J) i- S+ J) V8 x. m( }

  140. 9 m; @1 `" q/ G

  141. ) h4 {+ u  t0 O: E' H1 p+ ^
  142.         public bool IsReusable! m) H) X, J: E( ?9 m5 p/ J
  143.         {$ \$ ]# P* A6 \9 b$ s  O8 Q
  144.             get
    1 P, ?( ^5 q& Y" w3 ~+ ~
  145.             {
    2 @" v8 E0 l% ^9 j
  146.                 return false;
    $ }! ?9 g* j4 _- X1 k" o
  147.             }: G0 M  T: g" i/ X- J/ L! r9 @( Q9 p
  148.         }
    ( O; ~7 i  S% E+ c3 Y! d5 ^
  149.     }
    $ M4 g+ C3 P2 G2 O9 W$ o0 l
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

7 x+ `5 R3 X1 a  {. S




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