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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
' g! E, Y/ F6 Z* [) f5 N& g8 \
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
      z) v9 n! f( ^. r( A" i; x4 Y/ I
  2. using System.Collections.Generic;2 s: V, S/ n. U5 J% W
  3. using System.Linq;8 \* f7 b) a, ]. H
  4. using System.Net.WebSockets;
    : I% [; [% e8 E3 M% C9 X6 s1 h8 m
  5. using System.Text;7 A( t3 R  C# O$ r1 T9 l' B6 V
  6. using System.Threading;
    % O, a. I  }; Z$ l5 b) h
  7. using System.Threading.Tasks;
    7 P/ r  ?1 V/ |
  8. using System.Web;
    4 H  Q# g1 d0 N5 y
  9. using System.Web.WebSockets;5 W( |0 f1 z" [6 }1 G

  10. ' {) E0 p" ?8 N: {
  11. 0 [9 [% d. n  Y6 _, W) ~
  12. namespace WebApplicationWebsocketHandler
    ! ^% r; G# Y( ?: G; e# @, P
  13. {
    ; `. o, v9 t' X3 ?
  14.     /// <summary>: C$ a! p1 p, H; ^; @4 o% T
  15.     /// 离线消息, i: R4 O8 t9 Q
  16.     /// </summary>) {/ I) ]% p9 w9 w
  17.     public class MessageInfo9 ?. ]  w' P# z3 U
  18.     {5 f  t! s* P  @/ e; f5 T7 _
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    ( F4 g: j7 I7 k: J' Y  l  {2 E
  20.         {
    7 r' Z- u- F7 z8 ~+ N, b
  21.             MsgTime = _MsgTime;: ^5 g: o/ u* |9 C' ?
  22.             MsgContent = _MsgContent;5 B' g" d! \( c2 z9 w2 m8 q6 b4 q
  23.         }* S$ p/ y2 W+ Z2 \8 G- {" Y+ t2 V
  24.         public DateTime MsgTime { get; set; }% o$ j# Z6 q8 Y2 }' W0 ~1 u: h6 ~
  25.         public ArraySegment<byte> MsgContent { get; set; }
    9 F9 T; h* J  Q/ E0 p
  26.     }
    + T0 U; r9 E3 M' E
  27. , o6 j( f$ q* w+ z
  28. - |+ r1 F) g, {3 Y, a2 N, ?

  29. % o6 d% h4 z; k, X1 q/ S9 K
  30. ' ?8 j# H1 M4 a& }0 g9 l
  31.     /// <summary>! `9 H2 w, V% B: M6 G+ G) M
  32.     /// Handler1 的摘要说明" g: I( v& ^: w5 P
  33.     /// </summary>" \. o7 n) F# V3 C) ^' ~' S
  34.     public class Handler1 : IHttpHandler" O" ?/ ^9 w; }6 I: R
  35.     {. p8 @4 T: ?& n% H/ M  w/ [
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    / `4 L1 d0 A9 D1 F5 _
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池# S7 D2 u9 e6 a, h
  38.         public void ProcessRequest(HttpContext context)/ q# U* w; k3 _' _% N% q
  39.         {; {; T2 v7 G7 f6 W- e/ O) c* v1 z! G7 g
  40.             //context.Response.ContentType = "text/plain";
      Q+ B6 S, S& L
  41.             //context.Response.Write("Hello World");& N2 z3 m4 B& o( G) B
  42.             if (context.IsWebSocketRequest)* f. r, {% ]1 I& A3 i- ~
  43.             {
    ; ]; u# k+ a" j$ Q
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    $ c. l; u# j8 j# X) @' Y; O0 l/ h
  45.             } + {( c+ T( ~2 l' e1 s) A
  46.         }- b# @# h: K2 B/ S* s4 ?; `& M' c
  47. 6 ]9 ^& l9 p+ b0 A* o% Y! E# T
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    , R# n+ k8 m* B/ v% q+ ?8 P4 O
  49.         {! j( v4 R: z! B4 O& @
  50.             WebSocket socket = context.WebSocket;( s( M7 q, N" r0 f
  51.             string user = context.QueryString["user"].ToString();
    * ~: e! q- N6 u1 h  C
  52. / _" s; p6 L+ r! @! Q: y
  53.             try
    ! `/ L, H$ T: T
  54.             {+ `/ x0 Y% Y* W3 \+ l
  55.                 #region 用户添加连接池% \8 d( }) C2 ]$ g
  56.                 //第一次open时,添加到连接池中+ [) x" f1 r% _: Z
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    + |5 k: U% O. {8 n
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    1 A$ h7 R  g7 [- x8 f
  59.                 else
    . k( ^/ K. h2 H, O& k! }, A
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    , e' u- b* C/ |- u+ \
  61.                         CONNECT_POOL[user] = socket;
    5 e. {8 P; O: @: t' u# Q
  62.                 #endregion6 j# J  ?7 B# K- ~

  63. ( Y7 i/ G. r# d. u4 f9 M
  64.                 #region 离线消息处理! J/ g3 F: H9 d1 G) G; T" S
  65.                 if (MESSAGE_POOL.ContainsKey(user))  A# g6 K6 e7 v% }) t# s
  66.                 {. `4 c! |. B4 d( l  X5 q
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];( T3 }+ k. E& _3 [; F" F2 Y- ^
  68.                     foreach (MessageInfo item in msgs): _% L  C) q* r, |/ B
  69.                     {1 D: P4 b( l1 g6 ^6 [
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    3 r& y0 A( E5 G8 n/ C) P5 x
  71.                     }/ p% {7 |% `9 C
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    # v5 J% n+ t! w& {, r* y( f
  73.                 }2 I# [5 q2 \( k; q% l3 ?5 x
  74.                 #endregion- E' c/ I2 Q# X+ e. L
  75. / _6 |2 p! ]+ c
  76.                 string descUser = string.Empty;//目的用户
    3 r! d, b& o0 w4 y% p+ }( ]
  77.                 while (true)
    % w' B1 @) V* a: O$ h2 v
  78.                 {
    2 f% T. B8 x4 ~& s" A/ C
  79.                     if (socket.State == WebSocketState.Open)4 R' |0 s9 u4 U* \, }9 ^2 f. y
  80.                     {& c) \, t# N1 m& X9 V
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);/ V- f/ ^  d7 L
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    9 L. f1 q5 Z$ i7 d. [! P% _7 }0 p
  83. - f: g# x: A; j  Z: t: m
  84.                         #region 消息处理(字符截取、消息转发). s2 A' I' R  S& Y, |  g7 F- k5 k
  85.                         try2 _+ j9 d. j$ |. q9 M0 {4 A
  86.                         {- s* k0 k$ W+ N. K' n. S
  87.                             #region 关闭Socket处理,删除连接池" u, {% {9 a5 q5 C! L" Y( J
  88.                             if (socket.State != WebSocketState.Open)//连接关闭* I6 r4 N; @3 M9 i; z/ v
  89.                             {% W/ {. Z9 V4 Y$ }& |$ N9 }
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池! i0 i9 p9 f) \0 ]4 |) Q3 k
  91.                                 break;/ _3 O9 N' V; ?, l
  92.                             }7 y" F$ P# m/ ^3 l  B
  93.                             #endregion
    8 n2 Q) e7 b7 V+ I: U; o1 p
  94. 7 n# T, _8 j6 F; }% F/ z2 T* f$ y3 R! [
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息1 [9 `, O3 k5 z$ x8 {2 X
  96.                             string[] msgList = userMsg.Split('|');
    6 X3 {2 B3 t+ I" U
  97.                             if (msgList.Length == 2)% }+ L0 N) s# t* H4 J/ Y. `
  98.                             {
    ! K/ B2 b' V2 i% a4 L5 Z1 J8 N& G
  99.                                 if (msgList[0].Trim().Length > 0)
    ; G" p5 _7 u; A0 M
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    , S! n, s, k( W" @9 i- D
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    1 j! L3 K  _3 V+ X. b
  102.                             }
    ' f. N" {- C9 {5 A' v
  103.                             else- l0 N6 [& n6 D4 V3 R$ ]  q6 a' u
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));, I* J$ V# s2 ~! ]3 V

  105. ) j4 U' a3 H; K: u" B
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    ) Z5 F( z3 D( k! j
  107.                             {
    3 j# i3 @2 D. V0 Q3 o
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端, P6 k2 O5 o! Q4 \4 x. ?4 s, @. z; s' p
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)7 I0 w7 p" o. R7 Y
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    ' f* B( N. o' x& U4 d: }& E& h
  111.                             }5 p7 E! ~; v% {. I# b5 y& t1 K
  112.                             else
    5 q. ?! x: O5 Z$ Y6 @" g
  113.                             {7 v3 |! W9 r7 x! i
  114.                                 Task.Run(() =>) r( e! V( F" c9 t+ a" o
  115.                                 {5 I& v6 g" n3 _) Q
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中: w& C# |; |/ T0 ^0 ~
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());9 _% q; t) O- I0 P. f$ H
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息* T( l1 o4 V- `, i) o- x
  119.                                 });
    ) r/ U7 v# y: P4 ^2 b
  120.                             }
    5 V; J& [' V/ f; T4 t! P# |- r# S
  121.                         }" G4 p9 A' ^) k/ K9 c
  122.                         catch (Exception exs)" x6 ^4 j; m3 [+ j+ v
  123.                         {
    " _) o2 u, c; h7 @$ I/ r
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息! p; i4 k! k8 f/ J4 c
  125.                         }
    5 c" s" h1 B; g0 s, ~4 R
  126.                         #endregion
    7 v3 l, a  x$ [0 s7 y5 C: T
  127.                     }
    ! l6 J& _+ Y% O* ~4 a  F  I
  128.                     else9 s" ?' T; N! _6 O3 S# I' y8 k$ r2 c( ^
  129.                     {. l4 K2 _+ v# o4 T9 j% j! ~0 F. [
  130.                         break;) m5 T6 [: \9 k6 \$ G/ Y; K
  131.                     }. T5 u- P) U, k0 o' p. c' E- B& y
  132.                 }//while end
    3 b; t: `) v+ o' y) S
  133.             }
    6 t. o8 W+ N2 v$ B. K
  134.             catch (Exception ex)
    3 X7 Z* ]$ ]6 r# H8 f4 t" Z) d
  135.             {: j+ N: _6 n' r, D) x
  136.                 //整体异常处理4 o: h9 h( U7 Y( h" |1 e
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    0 R; q- V4 ?+ G5 D
  138.             }+ M3 b( I- O5 N6 r1 t9 H. s  f8 a
  139.         }
    - R( h. F+ v' J5 A3 U
  140. * S8 ^+ ~6 e2 b/ D( o& n
  141. 1 M/ I5 _- n1 Y7 Q" n- ?  @
  142.         public bool IsReusable
    4 B+ N5 g# O; S% ?' T, x
  143.         {* o% Z- Z- c# Q: N9 u% z. n# \& b
  144.             get9 A7 U: @1 s& ?: Z' P
  145.             {
    5 _6 t$ Y, t! J2 e5 m/ C* O( |
  146.                 return false;+ E: `# Q  {* T
  147.             }
    / f1 R7 r! G5 |& l
  148.         }
    2 o' x8 f5 L+ _; }6 n
  149.     }9 n3 t. x& U4 E+ w, w
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
7 V  e, N/ l8 a1 i* O3 {; A
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-4-30 20:52 , Processed in 0.059145 second(s), 23 queries .

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