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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
% W* s2 K9 q) |; D
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    ) o0 n. G! O; a: k
  2. using System.Collections.Generic;. |+ L( l0 i, ]+ G8 Z( y. A
  3. using System.Linq;3 r% \4 Z) I# T- S$ N: g6 J1 b7 p
  4. using System.Net.WebSockets;
    6 a" y0 w3 u0 r8 i! v7 x6 e% d- S
  5. using System.Text;/ B3 f6 ~4 f( f, y% ?
  6. using System.Threading;
    8 U: R9 P1 k2 Q! y
  7. using System.Threading.Tasks;
    . ^2 o% o- e1 h8 G
  8. using System.Web;: i  C) b4 S- T2 Y. e# p
  9. using System.Web.WebSockets;# ?/ k) S# O9 ?
  10. ! G/ m- C" O9 [8 t1 x
  11. , a; ~9 i9 Q: u" ^$ V& {) D
  12. namespace WebApplicationWebsocketHandler
    $ n9 d' S) x' U. g' `( ]
  13. {3 F. {5 Y; K0 z! B/ T! [1 G: x
  14.     /// <summary>
    , |) W0 s) f2 Y' s  O( Z3 c9 m# a3 H
  15.     /// 离线消息* L' L, s# w( r1 R; d2 _9 F
  16.     /// </summary>
    6 U: M4 u1 O! T, ]! y% p2 l6 k
  17.     public class MessageInfo
    ) c( X( m- Y( k' _' W/ q! p
  18.     {
    * B6 F. Z, e# x; s
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    ( Q: q. v1 Q) Y/ ^/ I! B" q
  20.         {
    3 `1 t7 K8 t3 ~: X0 E9 c- u  h
  21.             MsgTime = _MsgTime;! a" h- R/ l1 p- }7 b
  22.             MsgContent = _MsgContent;4 \* S' `9 R7 w3 |
  23.         }
    6 r7 J1 E. p# c+ V! ~
  24.         public DateTime MsgTime { get; set; }
    # @6 Q+ L2 C( X- S( M
  25.         public ArraySegment<byte> MsgContent { get; set; }
    ) Q+ g1 Q; C0 ]7 Y2 J% N$ V
  26.     }: B. k& l$ b( r  }2 s

  27. ' a) M0 h+ _+ P5 G4 j/ M1 ~0 l
  28.   o# M: Z3 Y7 ~! O  h6 z

  29. ) V' c+ ^# Y/ V( K+ k, W
  30. ; Y3 D) l8 }. o8 u( c- ?; u5 {8 l
  31.     /// <summary>
    1 p( f3 q& g# H
  32.     /// Handler1 的摘要说明9 P9 W) @! c. n3 l( y
  33.     /// </summary>
    ! @0 U. {$ `! }1 b$ w2 u/ i. e
  34.     public class Handler1 : IHttpHandler2 o9 |& Q# H1 G6 u5 V8 h6 ]
  35.     {
    : Z. l0 O0 R; q8 D( y8 O& [3 W  ~  z
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    9 v1 B" l: L5 b
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池3 r7 D! v9 T% B0 g0 A6 U
  38.         public void ProcessRequest(HttpContext context)3 }; J" r% y: x! k5 r" Z
  39.         {
    - ?0 w% q% n% v0 E& D
  40.             //context.Response.ContentType = "text/plain";
    $ l  g/ I0 i  b( V: U# ~) P$ ~
  41.             //context.Response.Write("Hello World");
    - j* j! w) |1 Q) R$ A0 x" m
  42.             if (context.IsWebSocketRequest)
    1 o9 o/ c  P$ C8 D( s
  43.             {% V5 p- j* Y' P+ i2 i
  44.                 context.AcceptWebSocketRequest(ProcessChat);2 ?7 T# r" K* `9 e
  45.             }
    7 M% i% J2 V1 z
  46.         }' w4 G" b0 {# D4 y: ~2 I

  47. # h- o+ S" l" w0 }5 D& D
  48.         private async Task ProcessChat(AspNetWebSocketContext context)$ ^6 U2 ~/ i. n% i; u6 x7 U# C. v
  49.         {
    8 g5 e0 e7 t. p& P2 A
  50.             WebSocket socket = context.WebSocket;! h7 ~4 T. h0 b" Y
  51.             string user = context.QueryString["user"].ToString();
    4 z, c) N  E8 r
  52. $ \- i  b" ~6 G
  53.             try
    - r6 w$ m' F0 t3 `8 N# z3 m
  54.             {% |/ F/ _2 w. ^/ Y$ a5 X( |
  55.                 #region 用户添加连接池
    % B9 X+ k* d- @7 ^/ b! @  l$ C
  56.                 //第一次open时,添加到连接池中8 \) Z* J% V0 W, y4 S& R9 V: I$ Z: C
  57.                 if (!CONNECT_POOL.ContainsKey(user))  S% V2 ^$ J$ m$ U7 t4 p. q. w
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    - B: S  }/ Y4 A( u( d
  59.                 else
    ( O& t; |& E! y1 ^
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    ; F4 h+ L4 b' [# i9 \( s
  61.                         CONNECT_POOL[user] = socket;' z) T# {  M% r
  62.                 #endregion/ E5 B0 m" Q+ N8 t; g
  63.   C7 c* y4 h2 P: e& x
  64.                 #region 离线消息处理
    7 b  Q# j2 F2 T8 e. |1 b
  65.                 if (MESSAGE_POOL.ContainsKey(user))5 Y9 o: n: D* v
  66.                 {
      M6 [" l6 r7 N7 [
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];. C9 \8 D" q3 b
  68.                     foreach (MessageInfo item in msgs)
    $ d2 {* {/ k! n4 }1 C
  69.                     {
    % a' P: u+ V6 E* F# H( t. ^( o% w
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);# o# t8 l/ O$ d/ F& {7 H) U. t
  71.                     }7 L/ D' |$ B' u
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    ' f' H# r2 t1 L* @% X& W
  73.                 }
    ' t: ?: a: N& o1 P* i
  74.                 #endregion! h$ U. j0 D2 o+ D6 P  {! R2 s

  75. ' [0 B2 L6 i- T, p
  76.                 string descUser = string.Empty;//目的用户4 C3 r% d  }0 D( J, K
  77.                 while (true)# s5 B* X% }" u+ k
  78.                 {/ ^, ?3 t: k  v' Q  o$ i  l
  79.                     if (socket.State == WebSocketState.Open)
    & V3 b+ ^# ~( f* ^8 h) ~( h3 k0 S
  80.                     {/ P, ^/ \. ?/ ?& X! e
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    ) L# e; Z6 [* n# a% a
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    % ]' B# X  E: X7 z, D& l6 x0 O& T

  83. ! I3 h9 e9 q  P6 x2 R& j1 H1 Z+ Z
  84.                         #region 消息处理(字符截取、消息转发): C4 i. y' C  E
  85.                         try+ f" a. k! i7 o5 v
  86.                         {
    ! h, [& Q! H$ }+ Z# e
  87.                             #region 关闭Socket处理,删除连接池" d$ G  {9 p5 q9 t6 c; z3 x3 k4 q
  88.                             if (socket.State != WebSocketState.Open)//连接关闭, D* R( m3 C6 |6 @. q9 W$ ]
  89.                             {
    # V* X7 S. B* ]7 w
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池$ l+ M% ]$ y; u8 ^' z* E
  91.                                 break;
    . m% o" u! ~$ f6 |
  92.                             }$ h4 I% ^5 P3 f/ O9 M: I# O/ r
  93.                             #endregion
    ! y4 _( ^$ T5 X
  94. , H5 O, ^' X( E
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息* z# x  ]& h# ~' b9 X
  96.                             string[] msgList = userMsg.Split('|');
    . q7 a/ {! k& J2 M. f: G
  97.                             if (msgList.Length == 2), ]4 U6 Z  V8 Y3 I& h! U
  98.                             {
    / s1 W2 H9 k# Z
  99.                                 if (msgList[0].Trim().Length > 0)$ u" v* c% X1 m, X- |  }
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户, W: f1 W. q0 u% k6 C. L
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
      L9 M7 g* ]/ u# Y! W
  102.                             }
    " v- g4 S3 t1 r6 r
  103.                             else
    5 T5 o8 v2 u( F  I( X. ]% ?& J& ^
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    ; G' _; k! Y! l; E! i

  105. 9 C- M6 i5 Z& W) \  }8 Z- h( b
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线* T/ T7 D! f8 x7 B3 U" T3 q- g
  107.                             {0 Y/ Y& R! m3 v+ q. w
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    7 R9 I: N: T, A2 `/ _0 A- I
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)4 z8 E- D' u$ a! R
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    + p" Q1 z" w9 v- G8 I
  111.                             }
    : T! \2 [6 V! A: a/ k* H( ]
  112.                             else* j8 o# d( \9 r- J7 ~, U# v
  113.                             {
    * X- t, W! h4 c7 Z( I3 [
  114.                                 Task.Run(() =>7 Y, n$ j$ D/ m* H% n3 U& P3 o
  115.                                 {+ E! A, Z! H0 Z& B3 m5 Z7 o
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    ( R4 b3 t/ g3 F# |
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    0 {- p: F+ r. E, o" ]
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    7 c* X7 X8 d- S- r8 |2 R
  119.                                 });
    2 N; z4 t* j6 R& L" ?
  120.                             }
    4 ]; w$ ^2 W$ v/ z
  121.                         }
    + G5 }( ?' w1 z' e0 g2 }. E+ _' V. P
  122.                         catch (Exception exs)+ D. w% N, b6 N# c3 B, I
  123.                         {
    $ r; G: V1 b9 g5 |+ D: c% c0 X6 |
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息& A& P. [. {* U2 p6 k( Z
  125.                         }" V0 G, h% _  F/ V( L
  126.                         #endregion
    $ z* i0 G6 q( ~5 K7 a0 s. }
  127.                     }! _' R3 _! F3 }& v
  128.                     else
    7 R  ?8 ?6 N0 o  e0 Z& s  E" g; [
  129.                     {
    ) F6 Y/ }: _  X* l, O  k3 x- o5 @
  130.                         break;- X, C8 q* G* v# T; v; j
  131.                     }
    4 m/ U" G% [7 I1 p. [; G4 y6 \
  132.                 }//while end
    9 w1 z3 U0 P9 N) _% X; Z
  133.             }( p- q9 A9 v. }. u
  134.             catch (Exception ex)
    . q2 }; \* J+ v" K
  135.             {( \/ h% w0 A4 ?7 f: L& T
  136.                 //整体异常处理% d* Q! w- N& P/ Q
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    2 N: G* w% x  |) }! ^1 @
  138.             }0 r0 e' h. k9 b+ L$ i% J
  139.         }
    / c7 X6 A" U5 C1 K# E! e& w" f

  140. + o+ Y+ i9 H( a6 N6 [3 O

  141. 7 D$ N% b1 D, ~$ r, I- a
  142.         public bool IsReusable
    ! y9 {, F% S! \) J# @: S: W
  143.         {2 u: N# `; ~8 D, }
  144.             get& ^/ u( `/ O/ r) W
  145.             {
    : s. {: D$ u. L
  146.                 return false;
    7 W6 o. n- r( R4 Y3 J% s
  147.             }# X- _+ e# ^5 \) a% i- K
  148.         }+ |) e" m1 h3 x2 t
  149.     }0 U& h; N$ Y: ?1 h4 a% s5 E
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
# C2 F8 a3 h% I' Y) ^
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-1-30 19:52 , Processed in 0.057654 second(s), 22 queries .

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