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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目

! S6 l9 q3 z% n
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;; `4 F3 E$ B# e* p$ ^$ F. k- `/ B
  2. using System.Collections.Generic;7 g! F  F: ^$ ^  ?# R. `
  3. using System.Linq;2 M( k) w7 P3 L0 u1 Y( d% x2 r* I- d
  4. using System.Net.WebSockets;( l$ a  V; w" X( e$ z$ W/ x& x' l6 Z
  5. using System.Text;/ C% x# l( u4 C# [
  6. using System.Threading;) |% |& F! U8 C
  7. using System.Threading.Tasks;' j0 K/ Y) d6 o6 E: O
  8. using System.Web;
    2 F0 o2 n2 F" q6 `
  9. using System.Web.WebSockets;
    # {1 ]8 g- W* B: q) v! W8 t, N2 f7 |
  10. 8 Y7 q1 h! q  f
  11. 5 p% u0 q1 c5 b4 u
  12. namespace WebApplicationWebsocketHandler1 K- \# ]! }% b
  13. {& B3 n% q7 q* U
  14.     /// <summary>  W  K; _9 _2 p; ?9 T9 ?
  15.     /// 离线消息
    9 I! j+ R. p9 O+ ^$ ~& n. v! q
  16.     /// </summary>  D6 y* D. B. y% Y5 g5 [! X
  17.     public class MessageInfo' R9 I' {: Q4 w- i" c2 ^
  18.     {
    3 C" C$ y5 l- ^: Y
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)1 X, M$ H7 O3 v0 P# ]
  20.         {
    : l2 x* O" n6 G& Q* N
  21.             MsgTime = _MsgTime;; [7 ]1 q) e1 b
  22.             MsgContent = _MsgContent;
    5 @3 _+ T! k7 i9 l) K# j
  23.         }0 A. o  ?. q% ?8 s1 ?2 r! w: j
  24.         public DateTime MsgTime { get; set; }
    ; {4 Q1 `+ e) t& D  N
  25.         public ArraySegment<byte> MsgContent { get; set; }
    / b# x7 R% B0 z! l: h; ]3 R
  26.     }
    ! U* w& a5 A8 `. t
  27.   X6 I  x3 r) ^% s3 J

  28. 8 r- C9 Z' O; E- t% W2 l
  29. " m2 `3 E/ z! \4 m% N6 P
  30. 9 P  T9 \+ z, u  _- m
  31.     /// <summary>
    & T: t. F* B9 j
  32.     /// Handler1 的摘要说明
    7 D7 z% m: q5 ^) X( t
  33.     /// </summary>" G& P/ I2 p8 G
  34.     public class Handler1 : IHttpHandler( ?% h. A% u- Z" }3 C, r
  35.     {/ B' c. {' ^( p! k4 I0 ~
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池! A; ^, }6 p$ V8 q
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池' d4 H9 \0 B9 e' ^# i
  38.         public void ProcessRequest(HttpContext context)
    5 p% M9 t/ q: y1 E
  39.         {3 W# H! K, \, ^# ^/ y
  40.             //context.Response.ContentType = "text/plain";
    - J6 h; E$ @6 h& T' y, V
  41.             //context.Response.Write("Hello World");
    / p$ g1 ~7 F! A
  42.             if (context.IsWebSocketRequest)' ?0 w* j" o2 m3 ^
  43.             {
    ! {: |! A6 M5 w1 J/ H" X
  44.                 context.AcceptWebSocketRequest(ProcessChat);& P: a$ I' ]* i( g6 a& x$ Z! W
  45.             }
    5 A, D5 c5 Y) N! H+ M( l! C! M% \
  46.         }  H& G8 K3 K2 J2 ^1 V3 n) h- p. y
  47. 3 E0 m; `8 S8 k* A2 c4 C, x
  48.         private async Task ProcessChat(AspNetWebSocketContext context)9 x+ \' ?  s  W
  49.         {
    8 T* Y& V4 V/ B3 Z7 W. I) s. Y1 C( V
  50.             WebSocket socket = context.WebSocket;
    , |- D! {  k2 k9 b9 j5 m$ z5 j9 Q
  51.             string user = context.QueryString["user"].ToString();
      t4 ~/ D/ q( J6 g9 ?5 ?' n
  52. * e+ y1 m" A* r6 N: f+ o8 o
  53.             try
    ) A1 J8 W0 [2 A; q# x1 K% R
  54.             {
    4 k1 W1 m: U" G9 e
  55.                 #region 用户添加连接池. ~+ B2 w5 C: k9 k* p
  56.                 //第一次open时,添加到连接池中' a! l' D+ b2 \: i$ t" e
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    - Y9 c. q( x+ U3 v' W( v, g
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    ( Y$ z0 C- J$ {: s4 T5 z& @
  59.                 else
    7 L8 w5 t' w3 c0 [
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    ' n" E  q% Q3 D8 B1 X0 P
  61.                         CONNECT_POOL[user] = socket;  P5 T7 ~" o+ a4 e
  62.                 #endregion7 b! N3 a; }( a3 e4 j

  63. ; N$ i5 o0 D5 ?% C6 l4 E7 g, |
  64.                 #region 离线消息处理0 }$ F8 `' M2 k, q: Q0 o( Y
  65.                 if (MESSAGE_POOL.ContainsKey(user))# e" Y! M1 `/ K5 S6 }5 {' M
  66.                 {" g% R9 r# F8 c* F+ |) ]
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];+ d7 n& J, z  W( D' q' I
  68.                     foreach (MessageInfo item in msgs)
    9 t" U8 v5 g; P0 g) e% Q
  69.                     {
    ; H) v& m' b/ C$ R$ v( Z
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    ; I  L7 l. L9 X( W4 t2 O
  71.                     }$ }( t9 H8 d2 K! I4 B: d
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息: ?7 G+ G( Z: _- V; d. U9 u
  73.                 }
    % i- a8 t8 z9 p7 c9 h
  74.                 #endregion; g. p6 l$ X" |; M. R

  75. 9 ?/ F% ^6 o5 w# ^9 E# f
  76.                 string descUser = string.Empty;//目的用户1 C. B4 X7 V5 w" r
  77.                 while (true)
    ) ^* [, N! ?9 o1 g  Z8 C3 J' @
  78.                 {. K# R: L6 _) R# V- H' q
  79.                     if (socket.State == WebSocketState.Open): u1 T  P4 P2 H
  80.                     {
    : C0 T" S* S0 d$ t/ N" \- s
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    5 ^# X8 {6 `3 E1 x1 j! i
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);2 V/ D8 V  [8 R) H, N% h2 z' s3 W

  83. / m" e8 _# _5 q
  84.                         #region 消息处理(字符截取、消息转发)
    $ h& E6 p! H: v: g4 Z" A7 f
  85.                         try
    & l6 T7 u* X6 n4 z/ y5 Q, Y0 h. C
  86.                         {- y; w; [- p6 s* F+ Z' e% `) ^. e
  87.                             #region 关闭Socket处理,删除连接池
    : K8 D8 x! h% A) V6 P6 T
  88.                             if (socket.State != WebSocketState.Open)//连接关闭* R8 ^  a2 Z8 @" E0 l
  89.                             {
    ! f/ K  M0 q0 C. ?' r" |
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    : }3 {! {0 `. X1 u3 c! V
  91.                                 break;
      I! k" ~' f4 ~3 b# X
  92.                             }# F, Q5 u2 Z$ W5 |  ~/ l1 H
  93.                             #endregion
    : p) Z% i; L5 |* ~: x
  94. * H  o. c6 U) j
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    5 W) ]6 C2 ^; L# o
  96.                             string[] msgList = userMsg.Split('|');
    ' W  p. T. N2 S5 t& ^/ a, K/ P9 E
  97.                             if (msgList.Length == 2)$ p6 z1 y8 s, z7 r4 r6 t
  98.                             {
    % @5 L3 N, e2 ^) @; H9 K
  99.                                 if (msgList[0].Trim().Length > 0)
    , q4 S) w! m3 _0 [. q" D
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户3 N$ t; S2 y( s, z
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    . G; v  n: g% k; Q
  102.                             }9 T7 [6 d+ _, t& r
  103.                             else
    + X: c# X. s* @  y0 a7 [& ]/ E
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));; `. F" ]" E- s2 D& d0 K' S: U

  105. : i7 G) p3 j3 W. q5 O1 l
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线9 ~+ O. ?# Z$ X) \, P
  107.                             {6 h; h+ f  d$ o
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    / n2 u1 K5 z4 _5 k, t
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    , H0 W8 L7 M7 z5 h7 q" t/ C
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    - p( K* _* Q$ W) Z# a7 T3 ]+ K
  111.                             }- c, P5 @; c; W+ ]
  112.                             else
    $ y/ A# V' U$ u' p
  113.                             {9 Y% `; a  N3 B' G, k  H: {
  114.                                 Task.Run(() =># s9 ~: w& B, r6 b! K; d% O" B
  115.                                 {
    0 k3 U! c/ b  O7 _+ a- ~
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中/ y) w+ E* e4 E% N+ {; [8 H5 m1 p
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());' L1 W% N; }: O" ]3 S, P0 P' c. Y
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    + ~: I; x' r- `4 ~5 ]
  119.                                 });+ f. L. [" f% V/ f9 T* B
  120.                             }
    # j: X- J2 m5 t
  121.                         }2 }; q! _( l6 z* b5 B  `! a
  122.                         catch (Exception exs)3 _! Y) N  l- s  r# B9 ^
  123.                         {
    ) v+ _! S5 |% S; H/ h" G% X# \
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
      ^8 G' a4 J( t* M3 q
  125.                         }
    ! u8 Q' L+ q; E8 p2 O& v
  126.                         #endregion
    0 x+ c* _2 {/ w4 X$ G' |, C8 q! S1 [
  127.                     }8 W% x/ Y. G( W. K- X! _  K( l
  128.                     else
    8 V) J7 z2 {# u: i1 A
  129.                     {. S+ Z; G8 B/ G& R# ~7 j; a6 T
  130.                         break;4 `* ]/ q) J  m/ \7 e" _+ [4 [. h
  131.                     }4 f- E8 f4 g3 B4 w0 D" k* n( q, ?
  132.                 }//while end
    ( _* p0 E3 |/ G. }1 H
  133.             }
    7 R: \* x# p0 z( D
  134.             catch (Exception ex)/ ]& W  y0 J* m! m
  135.             {, w1 l2 j# M- ^. Q1 a
  136.                 //整体异常处理3 K" m8 y# N; Q
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);3 i! X- D( M* a% O8 Q: _2 [
  138.             }
    8 e: I% O; s7 B! k& W) X' R
  139.         }
    ) W6 {+ Y" O( Z! g; |3 V; p
  140. 4 o: U: ^* _- Z: R/ o
  141. 7 `3 g% j' [- ~+ s
  142.         public bool IsReusable
    4 t0 ]( ^0 g( d" ?9 U/ o
  143.         {, `6 T1 W. Y( e) Y) x- G8 M
  144.             get
    ( ]) @0 p. A4 c( H4 }- Z
  145.             {
    & ?1 V# b* w- O4 [5 A7 J6 F: h
  146.                 return false;
    0 _; A) k2 N3 n7 k9 o
  147.             }
    # ?! |4 I4 {  U/ K( h& L
  148.         }
    2 |  O1 b$ D/ L2 m- Q
  149.     }0 F" y+ J( [2 P: n7 W( R# ]
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
: P) L+ \( J2 H- r4 O( m# {
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-8-4 23:59 , Processed in 0.057095 second(s), 22 queries .

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