您尚未登录,请登录后浏览更多内容! 登录 | 立即注册

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 12435|回复: 0
打印 上一主题 下一主题

[html5] 在IIS上搭建WebSocket服务器(二)

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |正序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
# [: K1 G2 |) W8 L. [7 B6 [5 B
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    ) M8 p6 y* D$ z) b2 r7 {2 `
  2. using System.Collections.Generic;) ^5 Y+ c: S. u+ M, G% u
  3. using System.Linq;
    % F1 o5 ~. ?7 ], W4 m
  4. using System.Net.WebSockets;6 }8 T) O3 s; I1 _3 A
  5. using System.Text;
    - x0 A, @: M! `% m
  6. using System.Threading;
    ! A# E& x# p5 V3 ~2 }
  7. using System.Threading.Tasks;
    & v' v5 w. x2 X# Z$ O. s
  8. using System.Web;
    0 o4 f, ^2 C9 O/ ]9 O% k7 ~
  9. using System.Web.WebSockets;
    $ d9 f3 P' b$ M1 @$ f' f* A, W( d
  10. ! a% L, s! L/ y8 r
  11. " i) C5 Y! I  I7 R& F
  12. namespace WebApplicationWebsocketHandler
    8 z% n& B! Z- g6 L  x6 v3 K
  13. {
      [0 o: R; ~: {7 d1 j7 `
  14.     /// <summary>
    : B: P# e1 R  G3 M% W( U, U. d( x
  15.     /// 离线消息% x1 C" i0 ?& S# Z* m
  16.     /// </summary>
      h$ U( i- [* J* L8 B# e! i' T% U
  17.     public class MessageInfo6 T2 X' X9 o& O7 w* O/ C7 r
  18.     {0 L1 O- e! v1 x  B- B
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    * r! r) v3 l6 W( Q' ^
  20.         {
    / I( b. z  T) K1 y1 L
  21.             MsgTime = _MsgTime;0 V4 H8 O5 z% z( y
  22.             MsgContent = _MsgContent;
    ' z1 f; n' I! @) ^" y
  23.         }
    0 Z& w4 j* m, X- v) Q, b
  24.         public DateTime MsgTime { get; set; }0 x/ E3 `7 C3 u: ?7 F2 I. z
  25.         public ArraySegment<byte> MsgContent { get; set; }
    6 V% {2 \  O% ?2 j1 a
  26.     }' G8 q5 x2 E/ p' y
  27. 5 B3 X6 u) ]: \4 R
  28. 5 c- g+ O1 _( E, t+ A9 G2 H% C

  29. % y' B- h! s+ z3 Y

  30. . ?" f: |6 E# u% [& z; w2 `( R
  31.     /// <summary>
    1 L' P3 I, t: D2 e/ Y$ ^
  32.     /// Handler1 的摘要说明
    ' E: O3 H' H/ N3 f( o- h
  33.     /// </summary>
    ) t8 ^0 N. F* @0 M
  34.     public class Handler1 : IHttpHandler
    1 q& V* v% V3 a3 P5 y1 k$ ^$ i) R
  35.     {
    1 ?- q, ^5 ]% S
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池6 l/ Z. ]* ]* w: ^
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    ( o) J, n2 G0 L* n* t: Q6 G
  38.         public void ProcessRequest(HttpContext context)4 G7 F( J8 }! v+ t! x# A
  39.         {
    ' F& c; ]3 S% l$ ?
  40.             //context.Response.ContentType = "text/plain";# L! y+ w! B0 d
  41.             //context.Response.Write("Hello World");' y3 w+ \  Y. X
  42.             if (context.IsWebSocketRequest)' U& u5 c% B9 b/ P- C
  43.             {, ]6 j) P# q+ ~. D0 _
  44.                 context.AcceptWebSocketRequest(ProcessChat);6 z- }) b" t; k- T+ ~  C% k
  45.             } ' Q( M' k5 L5 V' E3 d2 i
  46.         }# P4 |; O, E$ J4 S# ~

  47. + `- ~1 a( W6 P6 w$ G
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    1 U: g5 c  M  _; ?2 ]+ `8 w/ y
  49.         {4 `: b, l' E  z
  50.             WebSocket socket = context.WebSocket;
    ( ?! y6 Q- d6 ^! t. k+ E: k( ^; ~+ S
  51.             string user = context.QueryString["user"].ToString();1 z- t) j9 g3 ?3 j

  52. " R* h4 _2 l  y9 Z: Q2 ?8 p
  53.             try2 m! j" X) a( _7 Z5 B
  54.             {  A- L, g( E. Y& Q4 I  [# F
  55.                 #region 用户添加连接池! y' \1 Q! x" M
  56.                 //第一次open时,添加到连接池中. S1 z% S! H3 z5 l* R( d
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    4 n+ h6 Q; W0 w, N* e+ I* ?* o
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加$ L9 E: v0 V" O4 \- j5 d
  59.                 else
    + S* L  T2 h1 g( o; _
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    7 g2 j2 I# ?5 W( u8 F1 X  x
  61.                         CONNECT_POOL[user] = socket;
      z0 K& y  G0 p
  62.                 #endregion$ y1 j. x( e: P; h1 }+ D$ `
  63. 2 f6 _: E6 X6 A0 o/ _
  64.                 #region 离线消息处理
    % a! v. R6 }" u: O
  65.                 if (MESSAGE_POOL.ContainsKey(user))* M: G. Y$ N3 O  {4 P' t$ |: {& K
  66.                 {
    - S# Q4 Q' n, }  L
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    & F7 s' p. y' R- S9 M+ G
  68.                     foreach (MessageInfo item in msgs)) j: n( ]7 M" a9 s
  69.                     {: g5 q6 `" p: }7 e. i. x% y
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);2 ]$ Q; L& x6 y7 F& f( O! O, A
  71.                     }% p6 G  V4 w( M$ d  w& @8 G
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    / j0 A" L: |( Q& N% x7 U
  73.                 }- K4 E% a: P7 L1 C# F
  74.                 #endregion/ l0 i' C+ d  i4 m! ]! L4 j2 i

  75. 5 G! J" o) b& J$ [( A
  76.                 string descUser = string.Empty;//目的用户! b, G" V( V& I$ q3 Y* B
  77.                 while (true)
    7 n. E: l' B# {0 B1 v% ^
  78.                 {
    1 g1 p2 x& I- u. i3 I* `
  79.                     if (socket.State == WebSocketState.Open)" `) [4 V* \2 q7 C  {. w
  80.                     {/ ^$ f, B$ a. C: L
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);% f4 V4 B1 S$ [- u
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    % d$ U0 T9 t' O; h
  83. ! U' B) j& G1 f3 C" o! K
  84.                         #region 消息处理(字符截取、消息转发)
      k2 s. m- Z) s  O; b
  85.                         try
    ) ]1 f1 n+ ~! {4 u1 O4 i
  86.                         {
    ! [9 l  i% x1 E
  87.                             #region 关闭Socket处理,删除连接池
    ) ?) F" ~: K, S. g5 T0 a  I7 i
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    ( ^# s. A# n& P7 [) e" u
  89.                             {0 e6 q0 Y& o8 Y9 Z+ j$ C/ d
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池: I3 I& X$ h: Y2 M" r
  91.                                 break;
    5 [6 P4 j* x, N' n+ m0 e4 F
  92.                             }5 C6 D& W! F& l* B
  93.                             #endregion+ e. t# L/ b3 y: c, e5 x8 f
  94. ) ]% |8 A5 f+ u2 b6 J/ }
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息+ E! [7 N' S" h: X- J
  96.                             string[] msgList = userMsg.Split('|');
    & ]6 g5 M' T1 ~& n! j9 L
  97.                             if (msgList.Length == 2)! G1 W) r5 A; V1 [9 q! Q3 Y9 D, q& w
  98.                             {* Y8 h3 N2 `1 S
  99.                                 if (msgList[0].Trim().Length > 0)
    6 c8 l/ Y, {5 r
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户3 k( T2 P$ w  P+ e- x; z
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    : Q3 L; F! p2 C
  102.                             }" H# Z8 {+ K2 a9 w3 l4 X4 [
  103.                             else
    / z+ C: p! f+ h1 k
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));/ ~2 {$ y0 Q$ W% [" {
  105. - }- G6 M: U( M: G& O8 _9 e- M. T2 `
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线% p" L, y& N6 I& T( a8 ]# l2 o
  107.                             {
    ; A3 C1 E5 ^8 x, B: |+ t
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端; g$ a/ @4 n9 y2 G
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open), M8 Q  @5 b7 n7 @. m! j( p5 e
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);5 w. k! o! Z1 w( C- v. I. X5 V) j* k
  111.                             }
    6 O% z8 _* ]/ _& T( l
  112.                             else( @1 E. O$ z4 b1 y& B$ }" o) g
  113.                             {, I$ J2 v  P6 E5 {$ j6 |5 }* f! Z
  114.                                 Task.Run(() =>( n) h5 a$ p( ]0 l
  115.                                 {
    * N% x+ Q1 Y3 E# k( y
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    $ h7 R" T7 @6 R. C# y
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    5 Z9 u& q$ }9 U; l
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息4 O* E+ J5 I! M* e2 _  T5 c
  119.                                 });
    , z6 K4 x0 p. _
  120.                             }
    $ [& z; s! j4 Y% f& G
  121.                         }# w1 w7 I9 c4 ?2 e
  122.                         catch (Exception exs)  i4 m' g2 i9 j9 m, Z
  123.                         {) t* g* x5 A, x) y# B2 q. H: ~
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息2 A& }, _2 x- T- E3 e( p" A
  125.                         }" _8 U6 l/ y5 K% K* L
  126.                         #endregion5 M$ `' F6 A$ V% w6 T* v
  127.                     }
    2 l& ]- _  w0 A6 K
  128.                     else
    ' y+ n. e/ o2 {/ `6 W6 p* T
  129.                     {& Y# m# I1 ~( a
  130.                         break;
    ) h5 O. j7 g0 g# ?' w* V
  131.                     }
    1 ]! Z0 J  n( [3 `' p! m; V
  132.                 }//while end  Q- J7 u) K2 K
  133.             }
    / ~' {$ u( j' X
  134.             catch (Exception ex)  i7 S  }0 x2 y% \# l
  135.             {
    ! p" [+ g, q5 L
  136.                 //整体异常处理2 M+ O1 }. {' f) N  E
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    & O, U9 q; Z* N. M; _! W8 `
  138.             }, U% b9 _* i% ?& I$ ^, j8 |
  139.         }
    2 h1 @/ M- S; O3 D( i# O# o
  140. ) d5 V: Z7 A5 Y% ^- ?

  141. 7 K- K4 F$ u# Y0 Y9 [( T, \' A0 x
  142.         public bool IsReusable
    , T' `3 b2 H) s2 Y/ D; o
  143.         {# A- R  z6 q& O2 j. z. |# |
  144.             get- X* r4 s5 m1 l) V3 l  K
  145.             {
    1 m/ Y, @& X0 ^$ H
  146.                 return false;3 ~0 t8 V' |* k* i2 G
  147.             }
    & {3 j8 r1 {  j- {
  148.         }
    " J' F# ]+ r1 y, X4 X/ X
  149.     }4 `6 [) q9 t, j7 O% u
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

4 B5 b) K. N6 m, p, ?: \6 }
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-12-22 20:02 , Processed in 0.139420 second(s), 25 queries .

Copyright © 2001-2024 Powered by cncml! X3.2. Theme By cncml!