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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

; }: M  t$ D. ]7 M; H: f3 y
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;9 `( U7 g, q9 Z& d/ s0 ^  K" l
  2. using System.Collections.Generic;
    & H6 M. E' D5 Z  x9 F3 ^
  3. using System.Linq;
    8 ^& h( U0 u" x: {6 S
  4. using System.Net.WebSockets;9 x' B; d/ Z, M& t! s' V& ]( x
  5. using System.Text;
    + R3 R! ^% Y, d- f! ~
  6. using System.Threading;: r! h/ b5 P; v
  7. using System.Threading.Tasks;
      K9 a, T9 o: m( \4 O
  8. using System.Web;: T" T' h' m/ o! \
  9. using System.Web.WebSockets;
    / C+ e# t& g; D8 `; R

  10. 2 B# Q% |, V5 d" Q" r/ X
  11. 4 T  j$ l- U5 M" a2 d9 J
  12. namespace WebApplicationWebsocketHandler7 j& o3 r  g4 E  \
  13. {* E6 i. s( }) B
  14.     /// <summary>) B) W: J7 k0 @( X  i1 O, F( R3 l0 z
  15.     /// 离线消息
    % i5 W0 M( ^  Y* h
  16.     /// </summary>
    $ l! u) D3 ~7 x# H: ]
  17.     public class MessageInfo
    ! p! E' M3 Y; c( W: ^
  18.     {4 r0 p4 z( q. W! x8 w/ Z. K1 u  W
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)* m! {7 G  A, U) g' i% N5 x
  20.         {, ^% r: b1 S# X$ r5 i) A0 ?% x+ v
  21.             MsgTime = _MsgTime;
    % }, n/ _& h) M) s
  22.             MsgContent = _MsgContent;* l3 V2 X$ ?, Z4 y
  23.         }
    ( U$ S% T7 Q  z% h& G2 s
  24.         public DateTime MsgTime { get; set; }: P# [& z/ @/ [+ q) |. E
  25.         public ArraySegment<byte> MsgContent { get; set; }% i3 ^1 ]6 x5 h- T( Z
  26.     }1 Z3 }$ |# K3 C/ B* E
  27. 0 w7 c2 @4 M( E7 `, R

  28. & @$ }" d0 }& v6 X0 Q9 s  o4 [/ [

  29. ' }; P( u! S( O  a2 r

  30. ' }4 ~2 A4 R/ s
  31.     /// <summary>
    9 L& w' m8 Q7 O- ^' s
  32.     /// Handler1 的摘要说明
    % W/ S* W2 Q) b% o0 S6 q0 C6 h
  33.     /// </summary>
    & X3 ?' G5 y8 r, m, [
  34.     public class Handler1 : IHttpHandler3 T, ~# W0 P( `: k( \, v" ^  F
  35.     {: @! t- @/ a* e& ]
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池; a" u* T9 P9 E8 L) P# |
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池3 T% i4 b5 }- d1 j, G+ v1 n! Z0 Y1 J
  38.         public void ProcessRequest(HttpContext context)) Q! y, i+ i& w! ~; j0 b
  39.         {
    . W8 X1 @+ U" ?
  40.             //context.Response.ContentType = "text/plain";
    ; m& h8 I: _( b; j8 S
  41.             //context.Response.Write("Hello World");
    1 p, B+ h* `' x
  42.             if (context.IsWebSocketRequest). P& E5 Y$ X6 i  w3 |8 y, }; Y) X
  43.             {
    : l, |0 n+ E4 Q; D
  44.                 context.AcceptWebSocketRequest(ProcessChat);3 W* u$ [+ f6 o- O  M, e& z3 p. |
  45.             } - Q, c3 T9 ~( y2 j& _" L
  46.         }- h+ O8 A, r7 |9 T4 b$ Y% z
  47. 1 Q  p1 J* b3 h6 E) _
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    + ]8 r/ F, B% e- U. g+ A; M# Q& Q
  49.         {" D4 K3 r& s% N9 ]
  50.             WebSocket socket = context.WebSocket;
    # G/ H" N+ C- D$ o, W" n" U6 T
  51.             string user = context.QueryString["user"].ToString();. A' o& V3 C$ v4 z' y; ?  p! x
  52. 9 I: v& g; c/ R# e+ U( ^8 D$ A" M
  53.             try; W0 W& a; S1 e1 ^6 m5 s
  54.             {: o- r/ k6 ]9 `8 F' n' N; n! `
  55.                 #region 用户添加连接池
    9 L- Z* e" [, h7 @. O4 c
  56.                 //第一次open时,添加到连接池中7 d$ p! C- L" y' L
  57.                 if (!CONNECT_POOL.ContainsKey(user))/ m) c8 J& K* y3 u
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    3 u* a) e: K7 u  |! L
  59.                 else  w; }! g. h) P. G0 t: q! z3 Q/ k
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新% O# G" R' Q6 ]8 n/ T, f/ a
  61.                         CONNECT_POOL[user] = socket;
    7 u- K0 i* P$ X% C
  62.                 #endregion5 m5 y( b2 C6 A$ ~/ \0 [; z
  63. / W* K* S' a. ^# p0 y4 Y: O  ]
  64.                 #region 离线消息处理8 r& c# T. c2 a
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    * M. a0 U8 Y# ~* ^: y
  66.                 {
    % o0 d$ ^% f& K$ A" P' W& @
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];% b( W" R7 j. G/ h& q7 f1 G2 X' ~+ ?
  68.                     foreach (MessageInfo item in msgs)
    : J) M0 w. ]% X
  69.                     {
    2 i* k" `' y0 S) Q  P8 f0 f# ]/ B
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);  X3 ~' @: U% M9 ^0 d# e0 w4 ^
  71.                     }* z3 R0 Y5 M2 j5 }" {+ {( W0 L4 M
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    # u' w' @: J! d) J0 ~! b
  73.                 }$ W4 W4 Y% c$ H% b/ M7 L2 R4 O
  74.                 #endregion- {0 Q* g$ ]& l* e- j0 a

  75. ' C; Y# m0 e# u/ D
  76.                 string descUser = string.Empty;//目的用户: ], f" f: M: d) m
  77.                 while (true)
    # A0 y' T3 T- O# H; x* s
  78.                 {+ r2 x1 f8 w2 t0 S, E3 L! f
  79.                     if (socket.State == WebSocketState.Open)
    . ^( R7 D) j1 c/ n- o
  80.                     {
    , A' x. K; S& ]6 Z
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);5 Q$ x  i( B6 n$ w
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);3 c$ j3 l% x& j0 M

  83. , f9 a  B% V# c  E
  84.                         #region 消息处理(字符截取、消息转发)$ l7 q) P( m3 b1 Q# [6 b7 r
  85.                         try% [6 A7 r# r/ Q: g& ~# J; f+ `
  86.                         {
    : C$ I0 Y2 }: P! k& _4 @
  87.                             #region 关闭Socket处理,删除连接池' W1 |- `: N9 M) X" _
  88.                             if (socket.State != WebSocketState.Open)//连接关闭& O; G3 `; ^  A: j2 W4 v  f: G, f
  89.                             {- ^) S+ ~% y3 ]9 d! q  k, i/ r+ o
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    : n' C: ~% W) @' O' L5 X* c  W9 O
  91.                                 break;5 n5 U" K4 G( W7 J
  92.                             }
    1 f) |! Y1 X% }  ?/ `# L
  93.                             #endregion3 M! Y% H6 n. b$ c; {- @

  94. 9 T& O. D/ J3 c
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    ( z; w; g( K2 f
  96.                             string[] msgList = userMsg.Split('|');7 g, h2 e3 }+ i4 ~: ~- e
  97.                             if (msgList.Length == 2)
    , O5 H) ~0 Y! V8 _$ p. P
  98.                             {
    - _( t, D' I) R! ?. I
  99.                                 if (msgList[0].Trim().Length > 0)
    3 P" K3 h1 w  P/ f& Y8 X4 a- c9 v
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户# C" R7 t/ Y1 O5 X; D
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    ' X3 [7 n' j8 ]5 f& v2 F- l( E
  102.                             }
    ' E1 }( y# u% P4 x
  103.                             else1 [- Q+ y+ W) p/ E1 i0 k/ s
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));8 ?; ~2 w) g, n1 l; D- S4 W
  105. ! x( s' V, a. f0 G9 i( R1 H
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线( B" `6 N- K% w
  107.                             {- u7 ]4 @$ T; l. e# n' M
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    3 |; }% \& R  _2 w" n
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    4 r- m. c; v7 L$ j/ {! i
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);9 ~% z" {6 a' @
  111.                             }
    2 @$ C7 ?3 V9 {" z& D4 c
  112.                             else
    0 I% ?: i0 K. t4 D0 [" {- J7 d
  113.                             {8 Q) t1 h9 t: h1 L9 M
  114.                                 Task.Run(() =>% ^8 w, F, _" N
  115.                                 {4 W. ]# g' Y7 n- P8 G4 S
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中/ {1 |! o1 H; J6 r( M
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    / a  _1 k) \' f: a% c3 e
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    6 e. a# H+ u) \, P
  119.                                 });
    6 u# q! x+ O, P0 W+ V0 Z: l9 ]
  120.                             }+ Z! A7 [$ m* k$ L" A! n
  121.                         }
    ; L7 e- x; S. b0 U" C# I# u
  122.                         catch (Exception exs)) Z' ]7 V  r* E& \
  123.                         {0 b5 o5 ]% ^: E0 }3 q3 K
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    $ n5 p* e* l! B1 t$ H
  125.                         }
    + Q+ r: S  s! v3 n( p/ v& N
  126.                         #endregion* X" Y) j8 w; I, c. N, ^8 S1 e
  127.                     }! S. P3 \! S, W
  128.                     else/ u$ y* i; H: U9 p" {
  129.                     {
    : f. T& S; d& U) c
  130.                         break;5 Y( W( i9 _# S' b5 p& ?
  131.                     }
    . q* h) J% O- V4 S7 b
  132.                 }//while end  {* e( ?3 B: i/ _5 N. s4 Q
  133.             }
    7 w( u5 r0 b' `8 R# ^0 b
  134.             catch (Exception ex)
    1 a3 n0 I' l3 r" i- s
  135.             {
    / h6 A. z( A1 N8 _
  136.                 //整体异常处理& n4 T2 Q. d3 I& k3 j) ~
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    . S) X3 N8 W. ?; U5 q; u2 g
  138.             }
    3 i. E4 k; _; s1 K1 p5 g  c) E, C
  139.         }$ j- N. d2 y* a3 f" x+ G

  140. ' d! \- N4 [/ j+ L- S

  141. : {! A2 z& {" S8 h  |+ X( R& p
  142.         public bool IsReusable+ L; Q7 g& o' X4 E, N% `
  143.         {. r' E8 s7 t# r
  144.             get2 N/ U; n# w0 y6 ]
  145.             {
    # |, s, k, m6 b5 e* Y1 ~
  146.                 return false;2 z/ A4 N& b% C
  147.             }
      [2 F$ K2 b) X
  148.         }
    & P5 v1 n' X0 L9 a! M3 O
  149.     }! M/ Z/ o. d9 H  `
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

, x" R1 ~* e3 j* s& j6 y( h- ?
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-3-16 19:39 , Processed in 0.059512 second(s), 23 queries .

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