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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
! i% T& r& s% V! R
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;0 x9 s. I6 C0 Y. g8 J! d/ H, ]
  2. using System.Collections.Generic;, I8 G3 P8 p1 C" ?0 v
  3. using System.Linq;
    $ V3 R3 `: X; ^( Y9 w
  4. using System.Net.WebSockets;
    + Y: k8 c/ i3 D. b' m' |& N& {
  5. using System.Text;0 A0 v* j5 g/ l. S& M$ }3 H. l
  6. using System.Threading;1 C3 |/ J& x/ M% c/ H& }
  7. using System.Threading.Tasks;
    8 }' k) Z4 a5 k& p7 g8 L( b3 B
  8. using System.Web;1 {/ Y' J  H6 s& p& @  }
  9. using System.Web.WebSockets;
    & T% ?" y3 \( Y0 z) Y* R) z

  10. , Z+ ~& u0 x: _! h

  11. ( R* A% ?+ l% _: q! U) n
  12. namespace WebApplicationWebsocketHandler* N1 n' h8 g5 x' r0 y
  13. {2 x7 s  E: \4 g* g3 V. u! r" k
  14.     /// <summary>1 r2 d" A  r) \7 c+ B: e. W( h+ b
  15.     /// 离线消息7 x: Z1 v: ~, S+ V* K
  16.     /// </summary>6 z( c0 d! d8 f. b5 A" Y
  17.     public class MessageInfo; n. l7 O6 ?0 Z1 ^+ D1 s. S! E
  18.     {( B1 ^: R7 L* P; \( M$ J8 F, U
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)2 x  n6 t( O+ t* k$ r
  20.         {
    ! p9 l7 H/ ^3 y, r  d9 W* I( m$ b
  21.             MsgTime = _MsgTime;
    4 x+ ?8 d7 }3 F$ v- i$ m$ `
  22.             MsgContent = _MsgContent;
    , c3 ?5 I0 r! U2 Q! a
  23.         }
    . S7 K3 J- B3 ^+ F1 X$ k, z
  24.         public DateTime MsgTime { get; set; }; j% f# Z' K9 Q5 a- m
  25.         public ArraySegment<byte> MsgContent { get; set; }% O9 e. E2 O/ o% p' l, t$ K) H/ B; X
  26.     }  R( g5 F" }, F( F$ h

  27. " V( P; R2 _( J6 p9 a+ C4 @% \
  28. ) `9 K8 M0 Q0 ?; `- c9 T' f2 Z+ v9 q
  29. % l- b# ^& a* }% k9 N3 I

  30. 4 e# ^% q( D* X* t7 Q' I/ @
  31.     /// <summary>" r: ?# e' @$ v& \0 V
  32.     /// Handler1 的摘要说明
    ) B- m* B" k3 h
  33.     /// </summary>
    - m  w) ~6 R/ Y4 x
  34.     public class Handler1 : IHttpHandler
    9 |* q/ }, _9 b: w+ ^0 U
  35.     {% V* m2 z" J6 P
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池0 P$ w: m9 ]% Q8 E7 Y
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    - O( M& ]% Z- Y
  38.         public void ProcessRequest(HttpContext context)0 W# f, v( H/ S
  39.         {
    5 x8 `2 Z5 @  E
  40.             //context.Response.ContentType = "text/plain";! }' j1 T$ m% P# T" C
  41.             //context.Response.Write("Hello World");2 B0 [6 @" E$ M3 s4 ]( g+ N# D# Q
  42.             if (context.IsWebSocketRequest)! M. f* k7 W5 Q* b* D- y" }( l. o
  43.             {+ i5 U' t8 F$ Y0 Z
  44.                 context.AcceptWebSocketRequest(ProcessChat);6 B) U5 E: ]4 s" O
  45.             }
    0 c0 e$ d. `; [/ o: r
  46.         }7 \2 R% W5 D% n& U) L" n5 Y3 ^" L
  47. " d" `2 T+ o  E2 O0 `
  48.         private async Task ProcessChat(AspNetWebSocketContext context)/ L" U- f+ i3 k. l) p7 q4 y
  49.         {7 ^' w% k; y- Z4 f2 z  C( q8 r
  50.             WebSocket socket = context.WebSocket;" w8 D) [5 Q' I* V8 N  n2 R' U4 R
  51.             string user = context.QueryString["user"].ToString();& q( J( p) h* n9 p! K/ K

  52. ) e" w$ p7 @0 y' Z
  53.             try
    ' Z% W2 P. n' `6 `) J* d
  54.             {
    - ]' P. ]% H$ e* {' G3 z3 r+ r
  55.                 #region 用户添加连接池; N" M8 m! e) ]1 p
  56.                 //第一次open时,添加到连接池中
    ( k; {4 H9 [3 B  \/ Q2 Y
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    ! r3 q% t: y$ e: \  [1 J% N0 Y
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    5 d! F2 I9 @/ {" F7 @
  59.                 else% J# p3 x& z3 L2 S4 \9 t& k8 X* Z" l
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新8 C( ]( ?1 w7 g$ Z
  61.                         CONNECT_POOL[user] = socket;
    3 [2 x' |+ J+ V
  62.                 #endregion
    2 j5 Y3 [8 X# Z5 l1 C

  63. . g0 ?; S( P" N5 v
  64.                 #region 离线消息处理7 C! Y: r3 @! V
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    5 s6 b0 A4 c! u3 X
  66.                 {# v6 Y+ T2 K* E
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];7 U/ ]' ]5 O% c4 P5 i
  68.                     foreach (MessageInfo item in msgs)$ u+ b. g( L* \) `$ ]
  69.                     {4 \- Z( _( V+ j1 X9 ?; h
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);( B' J# \2 O( H3 k! P/ D9 I9 E
  71.                     }
    3 H! E$ d# |7 R8 `
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息, O5 ?" j+ P" \* J/ W
  73.                 }+ s( o8 q5 }; w, }5 E  d9 V" @$ z
  74.                 #endregion- g! i6 O( j( N

  75. 2 R- y6 {& F5 O  `2 u% ~
  76.                 string descUser = string.Empty;//目的用户- a' z% G+ _6 `
  77.                 while (true)
    5 Y/ A5 M1 U' F! `3 ]0 v
  78.                 {
    6 U1 ?1 T0 e, {/ ^+ T: t) n9 l
  79.                     if (socket.State == WebSocketState.Open)- H5 _5 E) U$ s) b$ x% K: d
  80.                     {
    / `) w3 n1 p' K# }+ T& h. d
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    0 u' w: t! @; w" C# Q- F3 R( Z- ]
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    # p$ |; }" v+ s3 z; y& ]; |

  83. - A/ D0 P% h2 s6 R1 v
  84.                         #region 消息处理(字符截取、消息转发)% `- ~* `) X: F1 y5 Y
  85.                         try
    $ }2 }3 J- K6 Q6 B$ E
  86.                         {
    - I; s+ R/ ], \4 x9 B0 t" B! F0 K3 {
  87.                             #region 关闭Socket处理,删除连接池; }: @! L1 {: C
  88.                             if (socket.State != WebSocketState.Open)//连接关闭! \1 Z' _% x/ `1 h% m
  89.                             {" h& C5 R# Y5 `& Y
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池1 G5 w; s6 P( n4 K* Y- k
  91.                                 break;8 s% Z/ U: R. w! M' X( P
  92.                             }1 V, i" s  [) g( L: g
  93.                             #endregion
    , ]3 V  |* N( U8 c

  94. : V, o% O0 w6 B. B* V3 [. {
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息5 L" z/ p7 @& p& f4 }
  96.                             string[] msgList = userMsg.Split('|');
    ) `' a" Q+ {; {
  97.                             if (msgList.Length == 2)
    $ ~4 E0 H* e' x+ K4 L# R
  98.                             {
    - s2 m% }! g) y1 P5 p. r
  99.                                 if (msgList[0].Trim().Length > 0)3 V  \: `  T7 i9 q
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    ' j, ?% b0 Z; O4 Q" R+ W# p4 ?
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    # {* M9 n- H: }6 v
  102.                             }
    9 S* {3 s8 P( }9 Q1 M
  103.                             else
    2 V' T* w8 w, g* R, G# P2 s
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    " j7 h5 Q* h2 _5 m; {
  105. , H: g7 [+ ~5 _$ W, |- }7 s
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
      ~- j- U! z- l" e" d- U1 u$ {, _7 |
  107.                             {
    ; d/ Z) C6 |% l  Q: e' M
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端9 k5 ]" K9 z8 o" z
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    / f0 S+ |' d! K
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);$ F6 ]! E) f8 j( r# C9 T
  111.                             }; K2 ^# Y/ E  e8 p" D, ^3 h
  112.                             else( _5 B& H% l+ e! @% w* k* _( H
  113.                             {
    3 b, }7 l3 j5 W5 A4 V* q
  114.                                 Task.Run(() =>4 R9 h+ i5 }7 q0 N
  115.                                 {
    9 b3 D/ p( z. Y
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中- f/ B! o# O4 Y5 p' K+ Y$ a# [
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());, b, U; \6 `) p7 p5 D, ~" _' g
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息+ Z# \/ g3 U" }, s0 M! g
  119.                                 });
    & Z' x$ n8 o+ ?" v7 s, F, K  Z
  120.                             }+ `$ t$ i+ B6 W7 V
  121.                         }
    - Q2 n% M! K4 l- x3 ~
  122.                         catch (Exception exs)
    , Y+ K. @) C+ ~$ Y1 B6 j8 k$ Y
  123.                         {
    # C' z- a1 y; p. z# X  V
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    : J. _* V! {* J6 }7 n# i  }% `. H- e
  125.                         }
    & ^1 v& n$ L0 x# n3 ]5 w- U
  126.                         #endregion; k1 Z- [& a% j9 \% X  w
  127.                     }
      m( b) A# D3 o
  128.                     else! J; U- k2 g, H+ i3 S& i
  129.                     {* @* _, M6 m! F
  130.                         break;& z' f: N+ n& c3 k
  131.                     }
    " J" D* Z( |$ j  n7 l* t  ~: m
  132.                 }//while end
    # x0 H; A( r9 g7 N+ ?; l! p
  133.             }; T4 P1 P3 q, D8 l: }9 T
  134.             catch (Exception ex). X$ o( |0 H) o$ c: L/ I
  135.             {
    . C& p3 h% X4 u: B# q+ x
  136.                 //整体异常处理- s, h3 z& ~8 i" n0 I- C' E7 B
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);* v( F- U; [9 M7 w
  138.             }/ m, F4 z/ z/ g" [% [7 h
  139.         }
    9 O5 [; d; ]" J" j( N9 u

  140. ; x- q0 m3 G& r' j) _! Q' H

  141.   u- p4 w" j0 W( w2 ~
  142.         public bool IsReusable
    ' G6 b- {, o# D! c7 }7 v
  143.         {9 U4 Z+ y/ I. s
  144.             get
    ( m+ U/ l5 e3 M- m9 M- U8 Q  f) b
  145.             {
    6 w) X3 h0 S) J% ?  _3 m
  146.                 return false;
    ! p9 K, K0 y8 {0 \" {- R" \' g8 z! K
  147.             }
    - Q" Y+ V) }0 u! M+ c3 h
  148.         }
    ( A, R8 y, `, u
  149.     }
    & X7 M& ~/ Q2 I% D
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

# h4 Z- l* M0 ]7 K
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-8-4 10:55 , Processed in 0.059235 second(s), 23 queries .

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