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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
2 e  _3 Q2 m0 f% }0 a+ c7 {
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;$ G" I3 D( |# Z& G) H
  2. using System.Collections.Generic;
    $ P( B6 N6 c& n
  3. using System.Linq;
    $ a6 P0 S, W& j8 ]6 _
  4. using System.Net.WebSockets;: O0 G7 Z" P, ~6 t0 V$ @
  5. using System.Text;
    ) U: b/ Y- R" ~$ t6 h
  6. using System.Threading;
    2 C2 r0 b" M4 u( k
  7. using System.Threading.Tasks;5 B1 D9 B  n+ D# k) e! z- G
  8. using System.Web;
    - |- v+ \, K& t
  9. using System.Web.WebSockets;2 F+ V3 @8 g1 `; [
  10. # m1 w& d5 o  ]1 A: @* y/ ~- @

  11. # ^: x, D/ \/ E$ J6 a' S9 a
  12. namespace WebApplicationWebsocketHandler! K) y: t4 J: Z, i/ M& v
  13. {: y5 p+ n, ]/ T: w( F
  14.     /// <summary>' E, I$ k0 T/ u- U& A9 l8 r
  15.     /// 离线消息
    ) h9 M. Q+ l' H2 K
  16.     /// </summary>7 k6 }( J# a9 T/ U7 T4 I8 N
  17.     public class MessageInfo9 W  e" F# [, Z( J
  18.     {
    7 I! V( D2 a2 \
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)8 ~& F: ]+ Q- Z* _# C2 X( V
  20.         {' a; l$ M$ v3 V! C1 o  R! \
  21.             MsgTime = _MsgTime;. b4 }  X6 D5 ?( Q: G
  22.             MsgContent = _MsgContent;
    1 |% z. N, F& U0 j
  23.         }, p6 c% G/ I% [4 h# b6 E
  24.         public DateTime MsgTime { get; set; }
    & g% m+ l% c, T! M& y
  25.         public ArraySegment<byte> MsgContent { get; set; }' B- }* T# r  o, B
  26.     }
    * Y' H! L( j4 M6 a! i% I* _
  27. - |1 G: k! J1 m. g+ H# x. {

  28. $ W2 u# g. \- X0 n

  29. 4 [! Y6 u' A- d$ `$ D" ?. X
  30. . x* M' M, ~6 }2 E5 u
  31.     /// <summary>
    ; r; z: V& [9 e. S
  32.     /// Handler1 的摘要说明
    6 R& t2 C9 f8 f( \* d
  33.     /// </summary>
    " W( U/ Y. F3 R* y7 W
  34.     public class Handler1 : IHttpHandler+ L  a3 a* ^9 M: x
  35.     {( I' r/ ]9 ~  I1 U. L. K$ Z
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池0 w) Y* f7 Y. [* [  ]
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    + d% G- ~; @& V  |, T# N
  38.         public void ProcessRequest(HttpContext context)5 M; o  H! ^$ U" `( T
  39.         {
    6 O( }: G8 G7 y/ l/ @: W. u8 t
  40.             //context.Response.ContentType = "text/plain";- _/ G. T; F; B: G* S  Z
  41.             //context.Response.Write("Hello World");# h8 e' s+ b. }5 }" v
  42.             if (context.IsWebSocketRequest)
    1 O7 `+ r- d" D& X, `
  43.             {
    3 Z$ Q5 W' o& p9 [- u) h' a. l3 U
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    5 c5 O+ K, U- f( r" ?+ ~: {' v
  45.             }
    % v' n0 E+ j, ?0 v
  46.         }+ b( r9 N! j# |# Z1 ^

  47. ! K4 h1 A6 i' s) z+ ?& {! O
  48.         private async Task ProcessChat(AspNetWebSocketContext context); h% ?) J! ?+ H4 Z' S+ g+ i: u
  49.         {( A+ n8 ~  D0 f
  50.             WebSocket socket = context.WebSocket;
    ! n* O1 I5 U* \9 P
  51.             string user = context.QueryString["user"].ToString();
    ) V8 M+ Q: X% P" V% A; ~/ E
  52. 3 b3 x) F. U3 T/ _( Z: K
  53.             try( p3 P/ s) X5 B0 r3 H# }# D- U
  54.             {
      v' }% @3 J" e0 R4 Z( k, b# E
  55.                 #region 用户添加连接池
    ( w0 F  `6 T5 S. d- r2 v5 c1 I
  56.                 //第一次open时,添加到连接池中
    7 Z) ~9 t$ N' s: O' B. ?
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    8 u/ k5 F7 e2 S" Z6 o% ~
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    * z: l' o: R. j& ]$ Y& _
  59.                 else
    5 f( t7 J3 d9 N0 N% k# c# g
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    ) K% r3 A4 j6 M8 W/ e: o
  61.                         CONNECT_POOL[user] = socket;
    ! _/ B5 E  W5 G/ b- n% ]
  62.                 #endregion4 g" Q. k% p. @) |
  63. $ A" O' B- I  A: x# g
  64.                 #region 离线消息处理1 p4 D; ^9 ^! h/ d; l# {# a5 N
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    3 }/ Q6 s0 Z4 Y8 F5 B
  66.                 {
    3 l2 Q. U7 k9 p  ?6 Y" X
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    7 x% q) p, R2 L8 [- I) u
  68.                     foreach (MessageInfo item in msgs)2 ]. `6 n7 q" f! u  D' u. C% f
  69.                     {; w7 O0 u3 }" X, s* F* J! l4 Q) y+ L- F
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);" F9 A0 g/ _% n6 B! X/ j8 X' f
  71.                     }: }% O0 f0 R) D$ S+ H
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息9 B& \6 C% D# {7 P# z1 }0 Q
  73.                 }
    ) ]5 Z& o( q- E7 i( v# ]* \! C
  74.                 #endregion
    + N  h: d6 p' o% r" g6 ?* `

  75. * L# A$ p& v4 n5 C; ]  L
  76.                 string descUser = string.Empty;//目的用户3 F2 F9 r: y: ?% M% x/ t, v
  77.                 while (true)
    5 @4 w& }7 b% E& O, ]8 _! y2 c
  78.                 {6 B: q% K, n) S1 Z# g7 [: _
  79.                     if (socket.State == WebSocketState.Open)
    % v1 V+ G( }& F; a2 Z2 l
  80.                     {
    . A3 g- B5 M5 J; D3 U7 E2 c( v
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);0 ~0 Z) g: ]7 V
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    - V. U; n" [) H/ G% I/ D5 u5 v
  83. 2 N4 x! ]7 \3 x! I
  84.                         #region 消息处理(字符截取、消息转发). r+ z  m& E+ w) [  w  D
  85.                         try/ z$ P3 ?: H) C
  86.                         {' P. N6 [9 s) \3 ]$ `
  87.                             #region 关闭Socket处理,删除连接池% _, Z7 P4 z! n( p% ?( p) s
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    ( V: w) `3 \9 Y, q7 U3 c+ z
  89.                             {7 d" S) g0 v7 t) o0 Y
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池7 _  I/ ^9 B" R$ w& h3 q
  91.                                 break;
    " Z' [  W" S2 N8 \3 ]
  92.                             }
    * H$ B' ?$ m1 n
  93.                             #endregion/ f; @( G9 f- V
  94. + w% m& K! N- ?% l; j
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息$ s; w& L9 {/ [" k. F1 U
  96.                             string[] msgList = userMsg.Split('|');
    + ~& q8 [! W' B  U1 E; A  @  g0 f
  97.                             if (msgList.Length == 2)0 f' Y/ ~* v$ v6 n8 z( P" ?
  98.                             {
    " u; n  M6 ~7 j$ S7 l, p, d/ f! Z
  99.                                 if (msgList[0].Trim().Length > 0)" d' t* f1 M+ g- J; N
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    + G: ]+ x3 N, d- n+ w3 ]0 k
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));+ J8 c  w  S$ M0 L3 B
  102.                             }. b9 }" t! `* s8 z0 _. y7 f0 G
  103.                             else
    : _7 q! F$ U5 ]% x- c
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));, [6 C! t$ @+ n. E; H/ }; ]
  105. * R5 K1 F. t# x
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    " j+ V5 E! R6 L) D
  107.                             {* H$ q. W0 I" t: W) y! A: J
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端! ?, G4 o$ Z0 w# y# A8 F
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    : @( c1 F) {& Y, e& i
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    5 m* Z8 [4 z2 `$ v
  111.                             }
    - W4 q, J$ f4 \0 A
  112.                             else
    . V3 {3 n1 T" N( g2 c+ O
  113.                             {
    3 s- I8 x6 q7 n; _: E! N5 I. h$ v
  114.                                 Task.Run(() =>
    6 T3 u4 H$ V" @# Q; D1 R" [# K
  115.                                 {
    9 O( O( F) w& J8 x
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    + i& M7 O, Z! a3 f- `
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());9 K; A  a) N# |1 t
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    % P3 N5 X6 C  ?! V
  119.                                 });
    # J& i. f2 c0 j( J+ _; H( f; d9 C& w
  120.                             }
    " N: n+ k  Y" }& g- Z# g0 M9 q- D
  121.                         }8 N- @  x( C& k$ k
  122.                         catch (Exception exs)$ @/ w( W$ b' H0 N
  123.                         {
    . x$ h" c1 A2 f! q
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息6 U- o* x1 J8 ~; k" g$ L9 f/ {/ _
  125.                         }
    , G/ ^$ l; p! I& a& W* W& p
  126.                         #endregion, O) a( m3 y+ K  s  p* l
  127.                     }
    6 m/ I0 y( i& v
  128.                     else
    0 e& O% b# }+ [
  129.                     {4 I* w. R1 r1 P! Q% y- G0 D4 `
  130.                         break;
    # E# r; R! q; S2 ]. Z
  131.                     }0 |, t' }: C* K% n/ J$ `
  132.                 }//while end. P0 u5 U8 q7 t+ o! a/ r* W4 V9 m
  133.             }
    1 K$ w' R/ K& I3 l5 p
  134.             catch (Exception ex)
    , A; |, r* q1 p& n+ r
  135.             {
    0 O5 \' u$ |5 Z3 k6 @. y6 a
  136.                 //整体异常处理
    8 }& F2 l3 c0 c4 i2 _8 q
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    ' L9 [3 o$ r, @: U* p) m- D
  138.             }
    7 @/ m( N: m" |( S# j
  139.         }" t7 D- J6 t3 o" T" V0 |/ H* p

  140. 1 Z0 S0 D) _/ p7 ^, F+ R! Y( d
  141. + P! d, M" z1 f
  142.         public bool IsReusable
    / I; b! Q7 o# q/ w
  143.         {
    $ g- q/ w/ e1 v
  144.             get
    ) t! G! T/ J" j  `
  145.             {2 |6 o# {6 f  \. |* z! a9 o
  146.                 return false;. k+ A" |5 H( }5 h- K
  147.             }) h8 ]8 o2 q  I; Y# v1 M- b
  148.         }! e0 [9 ^+ e7 b1 ^/ T% \
  149.     }$ ~3 q, m" t& }4 J$ C  c
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
6 a0 F8 C6 Y$ T3 l5 x8 [/ h
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-4-30 21:47 , Processed in 0.078628 second(s), 23 queries .

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