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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

  G7 Y5 E( Q, q7 l! r
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;6 [  u" y2 K$ K
  2. using System.Collections.Generic;/ {; @6 P; m. u( q7 \1 }7 A
  3. using System.Linq;$ w. d# M. Y3 \5 L- v8 ^
  4. using System.Net.WebSockets;
    5 Y& s8 _$ ~! B: a' v  y
  5. using System.Text;
    5 H% H4 n3 ?, P* U
  6. using System.Threading;* m6 q( ]7 x4 |& J$ b+ X: Q
  7. using System.Threading.Tasks;4 V" E$ f, |# q  v9 C' n% Q
  8. using System.Web;* x; e0 B7 Y' h3 ?# r
  9. using System.Web.WebSockets;5 Z1 ~% o2 p6 e# W

  10. # l! {) G/ A2 q# X) X

  11. 5 X1 s$ L& S5 F9 r3 l, ?0 l$ A
  12. namespace WebApplicationWebsocketHandler
    8 n, S2 K: z; U0 ~) V
  13. {% m% ^9 {( {( d
  14.     /// <summary>
    7 T8 X) J: K4 p# l7 |/ G2 Z$ o
  15.     /// 离线消息! L4 f, ?  ?+ j& y4 I- o* N
  16.     /// </summary>+ |4 |* z+ X6 V- F$ O
  17.     public class MessageInfo
    : T" A1 H1 ^9 {
  18.     {
    $ X0 t1 r* u  l9 Q3 h4 Q4 e1 ^
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    1 l7 |: y. C, Y7 Y1 b7 T
  20.         {
    # m6 {. p/ }# v: s# b7 Y
  21.             MsgTime = _MsgTime;
    0 G3 U5 h3 o3 T/ X3 o
  22.             MsgContent = _MsgContent;
    * b: g( m# @2 E0 ]1 {
  23.         }1 n. B5 F( F' Q7 |) e: z+ _- m" Y
  24.         public DateTime MsgTime { get; set; }
    3 B; z, e$ n1 t5 `& y- [$ R# B
  25.         public ArraySegment<byte> MsgContent { get; set; }) [! n$ u  Y5 D7 P0 _
  26.     }1 I: f/ L% g. ?3 I, f0 f* C3 j

  27. 7 i; q, L% ?6 s. O' q# v$ _( b( e

  28. ) I7 u! B5 ~; y5 g4 h, w

  29. 1 Z3 j( \# @+ R' x! g/ Y

  30. 2 p0 T+ C8 y* u  f8 v
  31.     /// <summary>' }( `1 ~" ?$ x$ s6 A6 E6 \) D
  32.     /// Handler1 的摘要说明
    $ ]2 O9 r  o3 H7 p
  33.     /// </summary>2 I( G; r2 f9 ]( S) }
  34.     public class Handler1 : IHttpHandler
    $ S+ g" h$ Q! G
  35.     {
    9 A% |- w8 G) Z
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池6 j( F2 l% z% R1 H/ e+ D7 G) }
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池, k+ h: q2 ]' E
  38.         public void ProcessRequest(HttpContext context); n) }8 Y* b- k0 E4 T
  39.         {
    5 L! @( A) p5 n! ]
  40.             //context.Response.ContentType = "text/plain";
    1 N, R) k# B* J1 H( a8 b
  41.             //context.Response.Write("Hello World");6 Q0 s8 U0 f+ a. z6 i
  42.             if (context.IsWebSocketRequest)' z' \1 {; A5 ^/ l2 b; G6 p
  43.             {
    $ D# O, u; M3 J, h3 g7 O
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    " w8 Q' b% ?" Z6 z& i) \
  45.             } ( j! i+ u2 O/ S9 ?
  46.         }
    $ a/ e6 f( a/ w
  47. - _0 j8 S" U9 p5 o' b) J! q
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    1 C2 t1 p2 H9 {1 K5 U' @
  49.         {+ L4 v9 U" t/ \
  50.             WebSocket socket = context.WebSocket;
    3 X( l2 P& J7 y1 n9 M# a
  51.             string user = context.QueryString["user"].ToString();
    1 |, v7 F+ G, V* i! i" @) O

  52. 7 H  |! h: V' _7 m+ i
  53.             try
    & `, v& E$ n4 B- f
  54.             {
    $ M* Q- R/ i! f- L6 j! R- G) j4 ?
  55.                 #region 用户添加连接池
    5 @! k8 A" T# f
  56.                 //第一次open时,添加到连接池中8 T, \: Z' a. B0 X$ Q' S/ U: {( j# A
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    " c9 H4 j% d+ _4 b- d5 p
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加- D. T$ k+ O9 d- ~& Z7 R7 @0 P
  59.                 else
    / W6 d2 k. V2 c8 h4 ]5 k( e6 W
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新% Y0 p) X/ l! p# r/ y3 L
  61.                         CONNECT_POOL[user] = socket;' H5 E, R& B2 m7 H$ ^) N
  62.                 #endregion! }# @. \+ v+ K, z! X! y% v( \' }

  63. 6 v- S$ }4 b% d  p8 f* J$ f
  64.                 #region 离线消息处理
    0 g% t/ Q8 q: N
  65.                 if (MESSAGE_POOL.ContainsKey(user)). t+ H7 o: R, S: q6 ]2 Z9 [
  66.                 {
    ) w/ K: C/ @# g6 t
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];0 w1 P) @8 b' r4 [
  68.                     foreach (MessageInfo item in msgs)
    3 V2 X$ R7 C/ y" E+ f7 c
  69.                     {% l: p) i* a' b8 |6 A+ i8 Z
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);, R' i2 L3 m5 O$ d7 N% ?
  71.                     }
    7 X: R# [- A; f! B, x* ?0 p2 ^
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息, l, Z9 C' o8 a9 e: _
  73.                 }/ {1 t) g; K" i+ O+ w0 G
  74.                 #endregion  U# S5 y! o# [. U0 q- @4 A

  75. ; S8 C! u: k9 c: A1 N* z0 }# m
  76.                 string descUser = string.Empty;//目的用户+ @: `+ s/ |$ [9 R
  77.                 while (true)& X, Q1 R4 E  Z' c) @# a) s6 O! e
  78.                 {8 g0 N" ?* J4 `# `& n
  79.                     if (socket.State == WebSocketState.Open)
    - X* ^: o, Z+ d  z/ w4 R2 U: f
  80.                     {; _1 J! G& Y! y, d/ b" \
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);+ l" P5 b) v; f" _% Y
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);, h4 W8 b' Q7 d0 `( f) {) E" q

  83. # L  {# ^. ]8 i/ k( c5 D
  84.                         #region 消息处理(字符截取、消息转发)
    8 j' |# r7 j/ e. X* h9 C1 d! M
  85.                         try' o; l" Y' K1 u; G
  86.                         {
    ( F! J/ {1 m& X" Z! p  y! K6 g
  87.                             #region 关闭Socket处理,删除连接池
    4 s; d$ I9 t$ [: \+ d
  88.                             if (socket.State != WebSocketState.Open)//连接关闭) }8 q- @8 S3 q' ~6 V1 K8 b  h
  89.                             {
    ( h7 ~7 t7 G$ h% C
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池' o! [& ?9 [; w% R1 K! U- Q
  91.                                 break;2 x2 |. H! \) n
  92.                             }0 q( \/ z6 D" R( V2 p3 u* I
  93.                             #endregion1 [/ i6 i# t' I3 Z2 w% Q0 Q
  94. 6 e. ]: O0 ], A( w1 R. F8 A
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息1 `* J" n, @3 f% r
  96.                             string[] msgList = userMsg.Split('|');. m- z% ~7 I, P( a* h- O
  97.                             if (msgList.Length == 2)
    * [. }+ U" k3 j1 N$ Q
  98.                             {
    $ O: U" m, ~+ O; {, x5 s$ L
  99.                                 if (msgList[0].Trim().Length > 0)" R. u) k1 j/ P/ G
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户2 @( q1 F1 t8 ]
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    8 D" l; P! X) s' `
  102.                             }
    4 R0 T: C  \5 h% ^9 V* F
  103.                             else$ I' b4 f; P* }
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));- T1 ~4 Z9 k  @2 s

  105. ( @* ?* B+ W6 @  g" S# v  E* N! t
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    0 ^0 H. ~: w7 z1 I
  107.                             {
    1 V, |# K# s7 Y( c2 K
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    & t8 D1 v* B  [5 i' {. f4 S! Y4 G
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)2 b+ @1 s! R% h
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    7 i8 J9 E& ?: {+ z( y
  111.                             }
    % ^2 T6 F6 L, B* ?/ t- x6 f
  112.                             else
    % A4 L7 ~9 Q3 e( w$ {
  113.                             {
    2 ?& [+ v3 h6 T1 F8 q0 P( U6 p7 Y" J% `
  114.                                 Task.Run(() =>( t" z3 X. s4 n+ U1 v; U, z
  115.                                 {* S. y$ c' R. F; h7 R
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    3 {) o: Y3 Y& E, d) g4 U
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
      z2 t- H% v; l! h- `
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息& F: B' z2 m, j4 L% s1 L! P1 K7 |
  119.                                 });
    & @; p8 D& v7 `7 O
  120.                             }$ j5 I" k0 v2 {1 _' A& P
  121.                         }. ~, ~8 a) @5 N  K7 ?7 O6 J
  122.                         catch (Exception exs)
    ) {) ?5 y$ m% k) I- Q! `8 X
  123.                         {
    , [& h$ _" d2 l! q! b
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息; L# h2 F3 E! l# J" f: K) v
  125.                         }  Q0 `% c$ ]0 c4 O3 T+ ~- E
  126.                         #endregion8 X$ ]0 j" l: W$ A$ T; \
  127.                     }
    : v& ?* j1 w; I  x" }) q
  128.                     else
    7 s+ s  H3 y7 R# e5 ^
  129.                     {5 G( D5 F4 S$ l* N' C2 N
  130.                         break;) T$ b5 |0 A/ R% T
  131.                     }
    0 }' W8 n* e. f9 T; Y& X
  132.                 }//while end7 C/ m$ d  t& Q8 G$ ]
  133.             }* x' ], v5 @$ U; Z8 j
  134.             catch (Exception ex), T: _7 X* o9 r+ w# w+ S
  135.             {
    & B2 A: d; j' t! k- `/ \' W
  136.                 //整体异常处理
    % @, D, \# U' H, h( X4 o
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    $ r/ U7 L; K! G; f2 |( i" M
  138.             }
    * w9 T9 y& c  c2 b
  139.         }' h/ W* c% W/ c: B0 o
  140. 5 ]0 e4 R6 p' q0 Q9 O
  141.   i3 M* E. [% b
  142.         public bool IsReusable" v" B2 c( v& t4 w
  143.         {$ u. ~5 o9 k9 c& w, v" X$ e
  144.             get
    + _/ h- L5 c+ C; o$ E/ m
  145.             {
    1 N- B/ K2 R& D# U& {# w7 }: T
  146.                 return false;+ G+ l+ d' [3 s4 s
  147.             }6 x1 @+ o. r; Z' E. t* Z/ @
  148.         }  L7 \/ ]$ ~9 T# [& B- Z! I
  149.     }
    & h* d# u" O/ N/ P8 S1 {
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

6 k6 u- j& N* Z1 g4 t
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-13 18:22 , Processed in 0.128462 second(s), 23 queries .

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