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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
9 R  H- a" k3 ^1 L* D% p+ n
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    % L% k: x9 d( @
  2. using System.Collections.Generic;& F+ C. i$ h6 w4 b
  3. using System.Linq;# k0 y  c4 y7 \! V
  4. using System.Net.WebSockets;
    5 P* y( Y/ X4 Q( c/ i, R
  5. using System.Text;* _* l/ U7 \9 D& c$ L! l% S' x
  6. using System.Threading;
    * g' z3 c7 t1 N: h- K
  7. using System.Threading.Tasks;: F$ E1 i! f! g1 ?- O% Q
  8. using System.Web;3 l, w. j- v* f% O( H  o7 L
  9. using System.Web.WebSockets;1 V! I* F/ E6 m7 U& O$ F
  10. - k% h+ m: J5 _; t1 A
  11. 8 l8 K! {- S( t" f
  12. namespace WebApplicationWebsocketHandler" ]8 Z+ G% p$ {
  13. {: R% {) L1 e, ~; _
  14.     /// <summary>
    6 y0 c: ~3 |: Q8 e7 Y& B
  15.     /// 离线消息
    : x8 P, c, d4 d- J  N* z* l* Z
  16.     /// </summary>" c$ q( k  z6 ?3 P. J2 x
  17.     public class MessageInfo- p2 G% g5 X( M  F% s
  18.     {7 i) _5 b9 Y5 F+ z1 y6 b+ o! E/ |
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)$ d4 f! Y. O$ N4 U% `4 B
  20.         {
    4 |- L2 m: g" c2 \
  21.             MsgTime = _MsgTime;
    & P3 X8 \) M  p! W; v2 K
  22.             MsgContent = _MsgContent;
    4 t! z; W" N2 {" Z* V$ l
  23.         }6 k3 p4 N9 D2 I) N
  24.         public DateTime MsgTime { get; set; }
    ' H5 R/ t4 |. K* ?7 A( f
  25.         public ArraySegment<byte> MsgContent { get; set; }# _* D) |* X( S! m; K. I+ m+ `3 y( x
  26.     }5 x; B* L  t; u  g- a6 U

  27. / |: S$ a$ p5 [. H8 l8 |6 n; V7 v5 l

  28. / N9 X! n" r* l7 Y% s

  29. ( }/ ~# m% C; e* F6 E# G! f
  30. 9 V( s  R5 i% n
  31.     /// <summary>
    8 u) I# ]" H. F& j" N9 O
  32.     /// Handler1 的摘要说明
    5 I3 B3 @" Y4 C( I  x9 c
  33.     /// </summary>4 T' u- O! C* i
  34.     public class Handler1 : IHttpHandler
    1 c7 n* j2 I* V/ f% m: t, c
  35.     {
    ' {& }  s# p7 f1 ~; p) F
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池0 l# t- B' _! `
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    2 C& n5 f1 L, Z4 n
  38.         public void ProcessRequest(HttpContext context)
    5 T; o: i1 S4 s- B9 h
  39.         {. {6 o& T( |% k" w" k* V8 [
  40.             //context.Response.ContentType = "text/plain";
    - ~0 Z& J5 r+ X+ @& O
  41.             //context.Response.Write("Hello World");* w* ^5 ]7 S' [7 r1 \
  42.             if (context.IsWebSocketRequest)6 D9 a. L# [- Y1 f" E* C
  43.             {0 e4 P! W" }: @! S. `: c" z
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    : G. _7 b+ b. i; X; I5 v+ d
  45.             } ! O" v6 c" P6 E" T9 d
  46.         }
    # a4 K/ {& p1 J9 L5 s
  47. . l! @; u  M7 H, O/ [3 K, D
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    # y3 G" U) H; F, {" o9 Q* T5 d
  49.         {
    8 o1 M% ^% B, g' C. B% a
  50.             WebSocket socket = context.WebSocket;
    ! S" I/ q1 A7 S% j
  51.             string user = context.QueryString["user"].ToString();; ~  S! h) H9 }5 L' Z% U

  52. 2 z& e& s* \7 w4 e
  53.             try0 o, o7 }% x8 B
  54.             {
    7 D1 B$ n* X4 E1 {2 ]4 E, ?4 r$ z
  55.                 #region 用户添加连接池
    / O% q+ q6 Y) L+ j( D+ M
  56.                 //第一次open时,添加到连接池中( D$ j* \$ `" _0 a, V
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    : p! V4 `! a& U* h' d1 r+ r" W+ I
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    2 B3 \1 ]7 P( z4 ?$ [, I
  59.                 else
    2 n; Q9 {4 Z: ]4 k2 w3 K& ~
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    9 K( D7 E7 Q5 a9 Z" ^# }. C
  61.                         CONNECT_POOL[user] = socket;
    ' G6 C9 Z5 P$ N- F& N
  62.                 #endregion/ g. C$ g7 c% d/ O* a/ X5 @
  63. : U: c' q9 B- M
  64.                 #region 离线消息处理
    , s% M9 x/ f4 k, a0 f/ @7 U
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    2 D6 d# E2 A4 N5 b
  66.                 {& u  M5 E( h( S* e9 j8 h
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];- b6 f, Q4 X, b& M! v3 t! Y! t
  68.                     foreach (MessageInfo item in msgs)( E& ^3 \7 E5 s+ N2 S0 D  @) @, U
  69.                     {* g4 `- x$ u; \: h3 C# `  m' E6 Q, e
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);% Y: f& n! B" g) t9 B
  71.                     }
    , S  l3 `' t+ _
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    : b: i! D8 @: V- S4 S
  73.                 }
    " w, r# i# t4 @/ ~4 j
  74.                 #endregion
    / R8 J+ V: v6 q. }! X  v

  75. ! ^* ^$ V$ f. e) D# {: `
  76.                 string descUser = string.Empty;//目的用户
    ( d3 y9 z- d: }$ f" l/ ?! v
  77.                 while (true)5 e. F6 _0 S5 u# N, V2 q+ v7 m5 X
  78.                 {  G( _  C- |1 U2 S- I0 _& x
  79.                     if (socket.State == WebSocketState.Open)
    7 K0 [: u" r8 s
  80.                     {# p* V( J: B* I1 ~6 ~
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);: s8 `5 ~1 b9 Q% O( w
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
      {5 X* |# [1 j
  83. 4 D! h  ]- z+ x' d. i
  84.                         #region 消息处理(字符截取、消息转发)
    1 B3 w7 ?- i7 e
  85.                         try
    - a; e9 W5 c# u! L: H
  86.                         {7 {+ r: V9 E8 \; [' W0 ]! S
  87.                             #region 关闭Socket处理,删除连接池% H7 I, |) s( q* n
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    8 n/ V3 p  H: _. K3 J/ c# t
  89.                             {+ E/ \6 D4 L- s. I/ s+ s
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    # T! P. ?3 c1 r+ V( f2 w
  91.                                 break;
    1 w. ]( B1 e/ E( n) p( j
  92.                             }
    + r& }; i. o. @; m" N
  93.                             #endregion" n- }, k2 U" k2 w

  94. 2 E! S+ q  o9 ?" t5 _& C5 N
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    ! `8 o$ T  \; b7 l' S1 ]& j* y  U
  96.                             string[] msgList = userMsg.Split('|');6 l% h9 h. y; m* L
  97.                             if (msgList.Length == 2)
    # f; u9 `3 V5 q" ~
  98.                             {
      M5 j, _6 G' w5 _* O  p
  99.                                 if (msgList[0].Trim().Length > 0)# g& J# W6 F) \' E: a/ i
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    5 h+ T# G' h% i' m2 h/ f9 h  e
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    : v3 o2 T, h" V* q; ~4 ?4 a
  102.                             }
    $ |7 q$ _# F6 W$ D  U
  103.                             else
    + u  O/ [( z+ N+ M" x
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    2 U4 y' a% z" W8 {% t

  105. ' U; S  L* I) h( d! S6 ^; C' N
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线, x6 W% e9 l5 Z& T0 T5 e% f
  107.                             {1 f3 Y  r6 T$ e+ b' Z
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    ; t& n% V2 E% C3 X0 t
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    ) r; ?+ @, S5 b( S5 Z2 ^$ y
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    6 l! Y- ~9 Y9 a$ N1 }5 }6 i
  111.                             }
    7 `1 b' x7 {7 A+ a- e
  112.                             else
    , _6 s" e. _3 K
  113.                             {! u: R1 J( }; k9 w  X' I' N* A
  114.                                 Task.Run(() =>
    # P: k$ B4 X5 ^1 t2 ~6 m; e
  115.                                 {
    / Y2 X; ^* Z+ G8 |; t; i& T
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中* o. S4 t6 v  }
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());& X( w3 c  ^4 u# g0 ?' S
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    & h6 C( y/ V& z, ?  K' i
  119.                                 });
    2 A* i' M( z  I" k( p/ N
  120.                             }
    + t" ?( N& t7 X; o, l
  121.                         }
    # R( ?6 }& g0 ^& k0 H* b0 }
  122.                         catch (Exception exs)0 t  P; h4 `2 e" @2 b* L7 ?
  123.                         {
    & _& |) U/ M& L! x$ u
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    2 S. \: F7 w4 Y. R- H' K' P
  125.                         }
    $ x( q7 Z+ D9 q3 I- x" g( K/ c3 y0 F
  126.                         #endregion
    / _8 J& i9 ~- A3 A6 i( O
  127.                     }
    4 s# l" X: k, x) s- G
  128.                     else
    * o3 r4 b$ w/ p5 P; k, m( G
  129.                     {
    ( u& R  {7 X- G4 R+ c" I- n
  130.                         break;
    3 `3 o) [" Z3 s; @/ N
  131.                     }( e" T6 Y; w+ k
  132.                 }//while end
    2 d" b( A9 t& p% y. P
  133.             }) ^; [; T1 M- \8 Q6 {5 y6 }2 _
  134.             catch (Exception ex)
      H/ h/ V7 m0 }3 ?8 w
  135.             {" l7 Z) T. [8 p4 _3 S( w9 K
  136.                 //整体异常处理
    ; A$ [. B2 w, u; D" ?+ k0 r
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);. e' N) o2 W9 T& [
  138.             }
    $ x. ]7 e( n6 X5 z( N
  139.         }
    " p8 s% P5 C0 Q/ w$ E

  140.   ?3 M1 b! D& f1 P: G; \
  141.   y1 y* U' e: ~+ E+ S6 Y
  142.         public bool IsReusable
    * |. S; t7 j( |
  143.         {
    . S: |) d- L! X8 O: b/ g8 @7 K1 P$ e
  144.             get2 y) B. ?7 ~$ d- K' X7 K( |
  145.             {
    ! t5 C+ U- O, t+ }* w' S6 k
  146.                 return false;
    ) L$ w" M( F' P# i4 j" I  ?
  147.             }* W) [6 f- i$ d" @6 G6 s) p$ B
  148.         }
    ' G7 }+ Q# P( s4 W& A* ^
  149.     }/ ^! c+ q# D4 X% r7 z
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

# K6 q8 ~7 C3 {5 g$ g6 |' \
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-3-16 18:09 , Processed in 0.061102 second(s), 22 queries .

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