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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 10261|回复: 0

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

[复制链接]
发表于 2018-11-7 00:43:37 | 显示全部楼层 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
4 W1 q; R8 K1 m! T' D
2.新建一个“一般处理程序”
1142009-20170426162840694-73221636.png
3.Handler1.ashx代码如下:
  1. using System;+ x9 y9 g8 a. ]8 e
  2. using System.Collections.Generic;1 W- m6 `  l! D1 P0 ^
  3. using System.Linq;
    1 V- {/ m7 U$ d5 q
  4. using System.Net.WebSockets;0 J' x. `$ q" z+ s+ W& |6 f6 T  x
  5. using System.Text;6 a# q: F% w3 f; y) o
  6. using System.Threading;
    7 B# Y. T- r3 e) z6 f5 C/ v2 t
  7. using System.Threading.Tasks;
    7 F% b8 S0 F2 D3 _! b
  8. using System.Web;3 U  R) c5 J; m/ V. q" u* ^' p
  9. using System.Web.WebSockets;
    7 P/ x. u: V" n8 }$ ~: O. W; z

  10. 2 w/ u3 \, a/ A$ j( ~" F/ ~% j/ S
  11. ! X% e3 t, W* \8 {3 h9 f
  12. namespace WebApplicationWebsocketHandler
    7 _8 @0 ^2 S+ k  j& a7 R
  13. {
    + k* H  t2 f( h) C4 i
  14.     /// <summary>
    " H/ h+ A6 b: I5 ?4 c: v* z
  15.     /// 离线消息- G8 S3 @' y( R( \
  16.     /// </summary>
    0 E4 o6 [/ S* E* A9 r
  17.     public class MessageInfo" @% a( C1 o+ E1 o5 ^+ y% D
  18.     {0 L9 i. i& |( l) M% A
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)! ^: D5 E( {$ M! p# I
  20.         {( O! F! v; @" y3 n* D2 a- g
  21.             MsgTime = _MsgTime;2 Q& I# f# o9 U# r4 I
  22.             MsgContent = _MsgContent;
    7 l0 o+ d. d4 c
  23.         }
    - w6 u, C# d; `$ W/ f& X
  24.         public DateTime MsgTime { get; set; }' m  ]& M9 |& M2 d  I0 \  i0 z4 P' L
  25.         public ArraySegment<byte> MsgContent { get; set; }8 }- F( D+ }! T# P
  26.     }/ ]) U2 r8 O& U1 N6 {$ K" ~
  27. 8 s; g) b, m& n

  28. 2 T/ k: l$ Q) a2 G
  29. 1 I6 D8 {8 z: s, v
  30. - q! j- ~) X( E1 R1 @# q
  31.     /// <summary>* }& i7 p% X' `
  32.     /// Handler1 的摘要说明
    # Z, ?  ^# u) ]
  33.     /// </summary>
    ) q! Q, e: b, ~3 g
  34.     public class Handler1 : IHttpHandler  A$ k, t9 j0 }/ Y0 K/ V
  35.     {# v2 V2 }/ X/ Z$ w0 N0 T  i
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    ( u& B( O! J) n1 G. n
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    1 v4 Z& m1 S& }) @. a
  38.         public void ProcessRequest(HttpContext context)- r. X( q$ @0 H- a
  39.         {
    / r+ e; Y- k/ w
  40.             //context.Response.ContentType = "text/plain";; w( S2 |: Y: g( G+ x* c( X% j& H
  41.             //context.Response.Write("Hello World");
    ) H! O/ |# k4 a+ [; J* n2 o
  42.             if (context.IsWebSocketRequest)
    0 |$ V' U$ D! {# H- C; L
  43.             {* N+ m4 N' g. c* ?' K
  44.                 context.AcceptWebSocketRequest(ProcessChat);- v9 J2 t- p- a3 d7 a7 n
  45.             }
    0 i2 ^' s+ p4 }* U
  46.         }
    6 V1 V" U8 E- l% N) M9 t& b

  47. ! m; y) X) n$ m4 y; r& Z
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    ( C0 N* j' W/ m0 P4 P6 O
  49.         {) G9 ?. S* y3 ]
  50.             WebSocket socket = context.WebSocket;4 ^7 F8 l% p$ v: i* {% w
  51.             string user = context.QueryString["user"].ToString();
    2 G. A* i( d; I5 E3 e7 `

  52. . x- S/ Z: {6 G4 T
  53.             try# t9 R; p  F/ ]' l; `; `( l
  54.             {
    # |( b/ F! B. ^! }; u
  55.                 #region 用户添加连接池/ u. @( t( H- h4 ~" `; N
  56.                 //第一次open时,添加到连接池中; r3 a" I  X' J  K, G6 V
  57.                 if (!CONNECT_POOL.ContainsKey(user))& X% f5 s# o2 ^
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    7 _, }  V9 C( C
  59.                 else! t$ x; u7 L: `  ?7 E( w+ Y2 ^3 z
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    , H2 a/ D: G: Z& _6 }$ m$ W
  61.                         CONNECT_POOL[user] = socket;2 j4 \3 {9 e3 ?
  62.                 #endregion( K: Z! t4 i+ j4 f

  63. , X/ ?! [  A/ p+ p4 A# Q. ^
  64.                 #region 离线消息处理
    2 a+ `; s' _( k, d' \: {
  65.                 if (MESSAGE_POOL.ContainsKey(user)). ~( q3 f+ {$ U
  66.                 {
    % a$ _' p7 t6 s
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];/ h" c$ x3 u, h3 C6 h
  68.                     foreach (MessageInfo item in msgs)! T) ?; ~  Q, p  k
  69.                     {
    2 q6 {2 B- c! U+ k( q8 _
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    ; {* O" I  _: X% ~+ Z$ m& E  S( M
  71.                     }
    1 l( T+ [8 A% z' @- [7 l7 S
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    9 ?$ P' H6 B! v4 T6 L# [
  73.                 }
    ' ]0 W5 F% B4 U) K: s1 z
  74.                 #endregion. u# b8 @' F% g4 t8 W
  75. * t: j, \' l: c3 l
  76.                 string descUser = string.Empty;//目的用户
    + u* n: g+ V$ m2 k- g& o6 I2 S
  77.                 while (true)5 v  h7 q& c& X
  78.                 {9 i% D3 [- ?. Q7 ?* j! W
  79.                     if (socket.State == WebSocketState.Open)& w3 a$ F% b8 |5 f; i6 I! L% u& ?+ ^
  80.                     {
    , J; T$ m- ?* b- k/ l  y, [
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    + \9 E9 D3 r8 M! x0 z+ _
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    3 ^5 e3 Q$ _8 k

  83. 8 |2 ?; v; o( Q2 K5 b5 n
  84.                         #region 消息处理(字符截取、消息转发)
    ) Z+ @* V+ @5 X' i7 l: F8 C
  85.                         try; o8 r/ ]% M) Q; \% }/ R: l% M
  86.                         {1 q9 k9 O) d: l2 V8 D8 c# k
  87.                             #region 关闭Socket处理,删除连接池) {' F+ F* D0 x$ L( \
  88.                             if (socket.State != WebSocketState.Open)//连接关闭, Q- p- S/ T1 ]; ]( Q! \) |! h4 K
  89.                             {
    % c& f* v2 F- r' f# Z
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    1 m& s% u2 E3 q7 M; U4 H, S+ @
  91.                                 break;
    $ X7 [7 l3 C) C6 K& b
  92.                             }
    $ \* c5 o  ^& s  h
  93.                             #endregion2 P/ \  Q/ K5 d) i% `

  94.   _' F1 ?6 b* r7 e. t) x& _
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息, Z  ~3 Z" V( B3 C7 B2 j
  96.                             string[] msgList = userMsg.Split('|');# y2 ]4 P/ N6 j/ R2 N
  97.                             if (msgList.Length == 2)/ a+ f9 x* w1 R- C2 z- I
  98.                             {
    7 v. h7 Z3 [' L  d& @: Z' J
  99.                                 if (msgList[0].Trim().Length > 0)
    ! Q% k* ~# @2 o8 x& R6 P. B3 O) b
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    . n" f  h6 O$ i5 V1 E0 D
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));6 k7 n) O  k1 V3 i* H$ G4 t  Y
  102.                             }$ }5 }4 k9 m2 d! H! D$ k5 t$ {
  103.                             else4 I* v/ K4 F! Z: F8 o+ n$ M
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));7 [3 s& m7 Z) |$ k7 H4 K
  105. " T/ [$ o0 {4 O/ ^, I: r3 ^
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线0 {& Y! A+ \" x+ l
  107.                             {4 V  r9 E7 v3 X; v/ x, M/ I
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    - C- o3 ?& t& Y3 k. k" o: Q
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)9 n. c/ I. M! Q9 Z% P9 v
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    & e4 m& p; m6 H/ M
  111.                             }
    + m" {* `3 `9 E
  112.                             else
    ! |# V) U2 x2 E7 a
  113.                             {
    - ^# ?0 Q2 z+ Q. x) R3 ?
  114.                                 Task.Run(() =>' ~6 K' B0 C1 q* G
  115.                                 {
    9 l# d. E! I8 o  j
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中# a/ |( v+ B9 \8 z2 T
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    - _# ]* j! \, Q" H$ Y5 ]. U6 ?
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    ) _, X8 y! T4 s$ v9 ?' t7 i" ^5 Q) z
  119.                                 });
    * B, m+ o+ _; ^& s
  120.                             }
    6 O6 m* t2 ]1 U& _& r. n
  121.                         }
    , ?% N' J1 K% O3 k4 R
  122.                         catch (Exception exs)) @( I# Y6 m  l8 h7 Z
  123.                         {
    ( \) S( m- R$ x5 x2 i
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息! j2 K8 G' K& P- q2 W* g% M
  125.                         }7 \/ L" s/ l( [4 w7 K0 ]
  126.                         #endregion
    + ^  D6 _, ^# \
  127.                     }0 ^7 k* j1 u6 H4 `- X0 s. a
  128.                     else  O5 v' {7 L+ k1 P$ R
  129.                     {3 w, |+ V) D2 ~2 X6 ?5 }# k* }
  130.                         break;
    : t8 S: E& O  H1 p! ^) L; y
  131.                     }3 e9 N  }/ S5 N
  132.                 }//while end+ c) R, i. C9 o& F4 G
  133.             }
      B1 E( Z* r5 j, M7 ?
  134.             catch (Exception ex)
    " P7 O2 o- E5 O/ s7 {( O
  135.             {5 ?: m. e5 n5 C7 j5 }3 M
  136.                 //整体异常处理0 {! P+ [9 @& O
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);3 K  Q; K5 T7 X
  138.             }
    * r8 y$ n1 H0 O6 x
  139.         }
    % w. h* ~6 V* z4 y/ ]

  140. 9 L; d0 I  C1 G* v% {
  141. 2 f7 t* _) u9 G
  142.         public bool IsReusable  S9 t* f" {7 `& O. Z5 ^3 G  o
  143.         {$ P) y$ b4 ?9 _! G
  144.             get, x% ^5 F- _' J, H
  145.             {/ ^0 @3 M9 w6 ]* G- d5 k- C
  146.                 return false;
    ! e; v( u7 D! \5 v  a# W2 `  h
  147.             }* B: Y6 h  H/ H0 J$ l& U
  148.         }8 R" l6 w1 k5 ~% d
  149.     }% ]1 s5 _6 ^; V: L
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
6 ~/ h! J5 H; g1 \6 V
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-3-28 20:59 , Processed in 0.134861 second(s), 25 queries .

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