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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
. G( N  `0 [, e5 Z& f
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    & N: r5 g% ~1 v) x- e
  2. using System.Collections.Generic;+ O" r, j" a: T/ g4 [
  3. using System.Linq;; H% p& k7 }- p0 X9 W
  4. using System.Net.WebSockets;) `' Q/ V$ \! R" R7 ]0 ?9 N! A
  5. using System.Text;. n# V- u3 @5 m. ^8 Q: b
  6. using System.Threading;& q' h$ I# F/ \& n, J- E( D0 @# c
  7. using System.Threading.Tasks;
    3 H( L* m3 m8 G  Y; ]4 R
  8. using System.Web;. l8 L3 V  R4 W! i9 F1 x: Z5 g
  9. using System.Web.WebSockets;
    4 x. {9 e6 d0 i$ Z& K8 t
  10. . N, a9 V8 O! D" W! H
  11. 0 Z/ S: g9 ^9 [
  12. namespace WebApplicationWebsocketHandler( f/ n% @3 }9 Y/ g+ U9 a
  13. {
    ! _* z( D8 Y; i1 x
  14.     /// <summary>3 y! ]" x0 _7 q  ~' D9 P* z
  15.     /// 离线消息
    " b: r& T* }* ]  G1 M  z! i' \
  16.     /// </summary>; t4 [3 ]0 A7 G2 ~: Z! _$ |% W/ ^
  17.     public class MessageInfo2 a& J' a, x7 b) u4 B) N7 _! d
  18.     {; y# R) ~! T9 F' z# D
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    6 y/ I) f2 i1 G; H5 y/ k$ `
  20.         {0 s/ z4 A) C" v! X
  21.             MsgTime = _MsgTime;/ v' V, _3 c+ ?& F% a& ~4 X0 p
  22.             MsgContent = _MsgContent;
    2 t( B" C# e! c
  23.         }
      m/ d, S; E6 [) {5 w5 k
  24.         public DateTime MsgTime { get; set; }
    ; c0 X# G8 ]1 t1 ?3 i9 ]
  25.         public ArraySegment<byte> MsgContent { get; set; }6 r1 w; t( j- }, J# K0 e
  26.     }
    3 Y  T$ F- }) M

  27. ) F6 E, O0 F$ [/ F: a8 D
  28.   h' J8 P" |. U2 E- y- M( _
  29. 4 b% ^/ a1 F: P; d6 `
  30. / A* G* r; s0 _9 ~: ~7 l
  31.     /// <summary>
    , D' {6 A$ }5 T7 a$ l1 M
  32.     /// Handler1 的摘要说明
    ) ?( q' f1 M3 b5 [2 j  U
  33.     /// </summary>
    ' A/ }; Z, P7 K
  34.     public class Handler1 : IHttpHandler% a% q6 V, h) d0 S6 ~' z, J
  35.     {
    5 m1 U) x$ G2 H8 ^3 ?+ @! m8 M
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    % y- ?) B0 x9 L, i3 t8 T
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池1 D. ?  A) T  c
  38.         public void ProcessRequest(HttpContext context)% {$ j2 _+ r8 E. |4 Q) i
  39.         {$ f" Y8 ]) U* `1 U) O8 i' ?3 P
  40.             //context.Response.ContentType = "text/plain";$ ]8 W, k; r, C7 D
  41.             //context.Response.Write("Hello World");9 l2 v$ M- j: D
  42.             if (context.IsWebSocketRequest)9 v0 w  B" E& S
  43.             {5 K: D& `7 l- o: g) S1 n& v" [
  44.                 context.AcceptWebSocketRequest(ProcessChat);: {4 d( [6 _, e
  45.             } ' z. I# T' e* b
  46.         }" Y# i+ {' O8 H$ i" ~" w0 S

  47. 2 J% _, g* V, T- i$ A
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    0 v+ K, x: s: o  O
  49.         {6 K+ }  j. U+ J" b1 W8 }
  50.             WebSocket socket = context.WebSocket;
    1 Q9 ]6 g. z1 m' m
  51.             string user = context.QueryString["user"].ToString();
    7 N, `; Y! R7 c6 z
  52. : e) q) V4 B; Z3 V) R  y6 p( ?
  53.             try6 s8 }8 D  ]( j' v* L5 c+ s: H
  54.             {) Y& M9 G' Z# n# o3 P, w3 B- ?: N
  55.                 #region 用户添加连接池
    & P- Z6 y5 d8 X3 ^" v& [
  56.                 //第一次open时,添加到连接池中
    ; `0 w' r0 ^2 B8 ]! G
  57.                 if (!CONNECT_POOL.ContainsKey(user))  a0 ^) ^- J' y# O" }6 y, i
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    ) K/ @; G0 z3 K& C1 n" l! n% ^
  59.                 else. I  w: Q9 r' V7 A$ w. D
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    8 [# j0 h9 ^- c9 x
  61.                         CONNECT_POOL[user] = socket;, v9 }$ \% a5 E9 {* D( s
  62.                 #endregion
    + @- ~: K# W# Z( @6 ~2 s

  63. % }: y8 E8 V" O/ ?7 @
  64.                 #region 离线消息处理
    $ v0 Z( t  o6 N1 ^
  65.                 if (MESSAGE_POOL.ContainsKey(user))% T6 R4 U; I; I4 l
  66.                 {; U2 {$ ]# E" W8 H) s6 D6 a0 W
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    - f+ w/ @. R* ]2 D1 x
  68.                     foreach (MessageInfo item in msgs)6 b2 s' a1 P( U+ b
  69.                     {
    7 R8 }$ \* {- Y6 D! \) v% R
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    9 F" t* R& U# h& w( ?, Y
  71.                     }
    ' v& X, L) P" ~& |
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    9 k) S; ?" C# J
  73.                 }, G' S8 F- R+ }. K2 q
  74.                 #endregion
    : c+ i* {1 `) ?9 Y) h
  75. / }9 l- p8 `! ?' d) e
  76.                 string descUser = string.Empty;//目的用户3 U+ a& O, P+ M% Z5 ]! o' A8 b
  77.                 while (true)
    , X5 S: q4 _, W8 P& f
  78.                 {) Z. D" E1 P/ W0 ^' d, }; X$ X6 U
  79.                     if (socket.State == WebSocketState.Open)6 y8 ^0 A$ e6 r/ M' _
  80.                     {, Z) j! G& n5 v" C7 T2 U/ H. z) d
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);0 q' }" I; k5 ^' m1 o2 z7 U0 j6 v' U
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    4 G3 ~& t, Y# X9 ^6 S
  83. 8 h7 l4 f  c' Y  ?2 P' Q) A
  84.                         #region 消息处理(字符截取、消息转发)
    7 \0 L+ h! m$ Z9 z" o+ H2 O
  85.                         try
      {3 |! [( N1 m7 ?
  86.                         {' Q5 J4 O( R! o; t2 |4 I4 ]
  87.                             #region 关闭Socket处理,删除连接池
    % Z6 J4 |/ u5 ~8 o/ x  }% I
  88.                             if (socket.State != WebSocketState.Open)//连接关闭# F# L1 k4 s( r8 L0 D4 Y
  89.                             {+ h, Z9 u6 I& P: K! [* @# }
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    ( u( w* Z; g" v) x
  91.                                 break;
    4 ~# Y- D! Q# `; g" F* B5 \, {
  92.                             }
    % I7 ]  E0 K6 |2 Y* x
  93.                             #endregion9 @- V0 s3 W+ Q2 L" b! t

  94. 6 v3 U1 W1 g- K9 j2 {8 o0 u- O
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    0 w. B" K0 j- ]; P+ W1 L( T
  96.                             string[] msgList = userMsg.Split('|');
      g" Q+ u- T2 `! @/ I# l/ |
  97.                             if (msgList.Length == 2)6 H, v9 \' T6 {3 Z
  98.                             {
    7 z  a5 D# s) Z& F8 W# p& z6 m
  99.                                 if (msgList[0].Trim().Length > 0)- B1 c- g, x) Z1 T% E
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    . X- y' m9 s% m! U& L( f2 n" D
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    9 b; G6 c' U, p5 Q7 U
  102.                             }
    . v5 a" n% I: v; T1 @& `" r
  103.                             else9 m' `7 ]6 y& @6 D/ [2 ]9 ~
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));3 Y, w) G) c9 M. P# `! n6 s
  105. 2 z) P- P: ?5 K( V: x
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线  a" e% X8 T1 ]% Q
  107.                             {! r! U7 J" j: B
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端4 F+ d; e( [& s6 `2 V" E
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    * }# }$ a# m8 |5 B+ {2 q- t
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    0 q6 P4 {! |; f4 n* c
  111.                             }
    + D3 F0 N* B. d$ X: _$ F/ o
  112.                             else
    ' }# `- e( h4 X9 z) F5 S
  113.                             {
    , H7 ~" T2 ~5 c% P% P9 t
  114.                                 Task.Run(() =>0 m5 S9 x6 q& u$ {+ `
  115.                                 {
    + S, P" d7 B$ n1 ?, a2 ~# E
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    ( a& \( [/ w! ]7 b2 h9 u7 J' M
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    $ y' y5 y6 V8 f5 O
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    + W9 W4 w' L3 F2 b. I
  119.                                 });2 R8 l- q8 o; U3 G; A9 J. M
  120.                             }
    9 W9 T- m5 e0 j' F# C1 _1 ?; o
  121.                         }
    $ Q5 u3 f6 |' ?; _# x
  122.                         catch (Exception exs)  F8 l1 a; z2 W# h( f
  123.                         {6 M/ d: i' X" X# [  o4 Z; |
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息6 |- m  ?5 P* o1 D$ \& l/ ]
  125.                         }9 F+ m6 ]5 M, c
  126.                         #endregion
    8 ?* p' h6 c: _: F" s9 S# p# _
  127.                     }
    * r, j& {, N) `* _* N
  128.                     else
    " _" f. i9 N4 t( g
  129.                     {5 E: u. D6 p; p8 N$ \; L' S
  130.                         break;: V) u  @) p- `  B8 S/ v3 Y" z
  131.                     }
    7 J$ Q  E- D2 l
  132.                 }//while end- g8 n/ J* s! s8 c7 {6 R  ~: |. S
  133.             }: c& m7 p; n/ X; \% a* Q3 \
  134.             catch (Exception ex)
    : X/ t( y% }2 v- N5 K# b  F
  135.             {( g% \7 j8 p2 u+ h* W4 b8 p
  136.                 //整体异常处理9 k* T5 |6 Y, x' P3 W  [. O
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);( |% H! L1 D$ X+ J4 I  o6 E' |
  138.             }/ z1 O- Q9 z+ V) b
  139.         }
    5 t4 B: o( {* n6 ?; i

  140. 8 p* A8 ^9 ~4 {0 S+ j

  141. ' ]6 E  d+ U5 O* ^! p$ ]6 s
  142.         public bool IsReusable0 X4 L9 p; o2 n5 `( v& R) ]
  143.         {7 [+ ^6 x3 B2 R1 ]1 @7 Q8 S, b
  144.             get
    0 t0 e/ a9 n" D( m
  145.             {$ E, ?  r" T4 G( e$ w) f8 n
  146.                 return false;8 `! D1 Z2 A( m
  147.             }
    * J* i' a  q4 _1 `* b
  148.         }
    5 G5 j' `# u9 J( r. Z6 Q  l6 a' O2 Y6 `
  149.     }
    $ K8 w5 F. Y) X. b3 I. f
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

. ^' G* C$ O3 P! E
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-6-20 02:44 , Processed in 0.064458 second(s), 22 queries .

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