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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |正序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
7 |/ _; ]2 d7 L' C5 Q
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;; A/ S# G. i5 T5 n& l$ e
  2. using System.Collections.Generic;
    & a" X; J  K  v- b
  3. using System.Linq;
    ( M" J8 p3 ?7 |7 y$ @6 O1 R4 i- L
  4. using System.Net.WebSockets;
    2 u. Q( e0 L* s" I$ D  `& R
  5. using System.Text;
    1 e+ @4 N/ k) Z/ |0 N( }' `* H
  6. using System.Threading;
    % j, J2 ^( N- S, _6 V% ?
  7. using System.Threading.Tasks;* q# q/ m* F  x: c" v3 y) M, p
  8. using System.Web;; d8 G$ r& d2 f( e/ Z' Q
  9. using System.Web.WebSockets;
    ) N/ @$ p+ O' p: V

  10. 0 I; J# e$ D1 a

  11. " v9 ]5 v# Y& _7 f* y& }
  12. namespace WebApplicationWebsocketHandler
    ; o% {: W5 a/ u. [, E8 R6 Q8 f8 V1 E( W
  13. {
    ! \- p6 ]! t, e% ]/ q
  14.     /// <summary>6 e- x6 n1 A: B6 G" O7 |( [
  15.     /// 离线消息
    1 p# C1 o6 V  x( w2 q# c
  16.     /// </summary>  O1 y1 V2 d+ B- H6 q& y! X
  17.     public class MessageInfo3 a$ L+ E( N: C& a8 V# e0 p4 J
  18.     {
    / i7 L* E/ j+ [
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)3 Z  D' u) N: H
  20.         {5 }  I  i# d3 b6 I8 f
  21.             MsgTime = _MsgTime;
    : `$ y: s( z5 O# W0 w/ n
  22.             MsgContent = _MsgContent;! I9 _* h' z/ j: ]
  23.         }
    3 |0 V1 N* j" p5 D+ h
  24.         public DateTime MsgTime { get; set; }
    3 Y# L0 N- t8 Q
  25.         public ArraySegment<byte> MsgContent { get; set; }
    9 x; [# K- b/ Q" {  m3 o
  26.     }/ E" B6 L. o! X+ i6 P) a

  27. & V8 S& I9 O4 i4 C) a3 u! ^

  28. ! k% e! r5 p. n& D$ e

  29. , O3 w0 _- x  s4 [% h! P2 x' O
  30. , n6 b- `% E* d
  31.     /// <summary>
    " F. x$ I: L9 O) b# z6 K
  32.     /// Handler1 的摘要说明% A: J, }  \" k% r
  33.     /// </summary>
    , D' j; J' M: m7 u8 B# u
  34.     public class Handler1 : IHttpHandler2 A. O% N4 I& S% G; B( `
  35.     {
    . d2 b2 b2 C1 L  P! Q
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    7 [5 [: i5 `9 m3 L  d6 H
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池  Z0 c: `9 B) Z
  38.         public void ProcessRequest(HttpContext context)
    - v) h+ i+ c/ E# F* M5 q
  39.         {. S5 ~9 r3 F8 s, b
  40.             //context.Response.ContentType = "text/plain";
    , u2 ~4 c5 D! `
  41.             //context.Response.Write("Hello World");
    $ n5 g0 U: N# I/ f
  42.             if (context.IsWebSocketRequest)
    1 n% J/ @  K4 f
  43.             {
    # B  f# i" a% t1 E0 ~7 a% y8 T& }
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    * N3 ~, I9 m% C& v$ k
  45.             }
    # m$ O, ~( R0 W% B7 d' x; f  p
  46.         }4 b+ v1 J; d7 k) }
  47.   b8 S, r1 y5 `, f
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    3 H% J) B; b  ?, z  ^4 S! k2 U" K: z
  49.         {
    ) ]- x$ k4 H6 k- x
  50.             WebSocket socket = context.WebSocket;
    ; G6 Q1 c( Y" e: ?& `
  51.             string user = context.QueryString["user"].ToString();
    0 v+ z4 T. j' h4 L* v8 d

  52. - V" t! m4 m9 F# G' {0 b
  53.             try
    # X' X8 }! N3 Y, v
  54.             {
    ) ~: \# H8 J4 F) t8 [
  55.                 #region 用户添加连接池8 X# d" ]9 Z9 ~+ r& |2 g
  56.                 //第一次open时,添加到连接池中# p$ y) x7 t& q* _
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    $ F. A# F2 @* V0 u4 {% f
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    5 r9 k1 n$ l4 G) ]" j
  59.                 else
    0 O& I+ j$ X+ k
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新+ C7 @1 B+ F( T3 f
  61.                         CONNECT_POOL[user] = socket;
    / J, t: n: j. ?, U6 l  R+ G
  62.                 #endregion" z% U; K8 H5 g# @3 k

  63. + X1 k: h, }1 r+ u/ f
  64.                 #region 离线消息处理2 q! S' N: m; k/ N9 q
  65.                 if (MESSAGE_POOL.ContainsKey(user))* P* i1 N' ^5 y" O3 ]1 C/ p# o
  66.                 {
    # @7 k8 \$ m( N9 ]" B' `8 w
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];! q8 |3 W3 o5 p" q3 Q
  68.                     foreach (MessageInfo item in msgs): R. g2 N0 b4 R( U0 [) x/ ]) p
  69.                     {
    4 y( k. {  d9 I7 W; i, k
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);! |# N, n/ Q; b$ D
  71.                     }
      }) `9 P4 o5 }$ J. ~; V) F! e
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息6 v. S6 E, g' K. i( P/ b) D
  73.                 }
    " O7 l+ o1 Y  J/ d5 h! d' y+ q
  74.                 #endregion0 y% N. ?$ I$ u

  75. 1 C  F! Z) ^1 d( X5 y9 u6 j
  76.                 string descUser = string.Empty;//目的用户
    4 w+ V/ I, h( j5 ?# R  t
  77.                 while (true); H0 Y! w2 f: i" D  x+ C
  78.                 {( c  u. \8 @6 [" M0 q
  79.                     if (socket.State == WebSocketState.Open)( ~* }6 c0 E) J: V5 Z* Y/ Z
  80.                     {. h; B8 b! o4 L& T6 |! i
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);3 B! m/ s/ n5 Q4 d8 ]; W
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    1 I4 u& e, v5 L; P" A% L9 P
  83. ; d2 \- R6 d' f! c9 x
  84.                         #region 消息处理(字符截取、消息转发)* \9 Z3 a0 m: M# \4 h. V2 e! ^
  85.                         try
    / {6 r' P; x9 ~+ q4 ~1 _
  86.                         {
    3 \) ]6 l) T' r) v' y; F
  87.                             #region 关闭Socket处理,删除连接池4 v# K; Y4 P$ T3 K$ T: c
  88.                             if (socket.State != WebSocketState.Open)//连接关闭7 O! g  }4 {8 C. A6 U
  89.                             {
    8 ?  I5 F+ \1 N6 o. e
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池1 `3 G7 b( X3 O) B
  91.                                 break;: O# C3 H) U4 V( j$ n
  92.                             }$ u3 e- V! l2 P+ k% z
  93.                             #endregion
    $ T; ?5 N0 S5 a3 j: u3 `
  94. ' g+ n+ [4 l* P2 D5 P( S
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    % l% j* X$ L2 A: F2 N- x9 V: h
  96.                             string[] msgList = userMsg.Split('|');
    5 R6 G& o' I+ a( |& c, m
  97.                             if (msgList.Length == 2), k' J, Y; S0 H; l( v6 N" ?4 B
  98.                             {
    ( q" Y+ K, m; E" c3 R
  99.                                 if (msgList[0].Trim().Length > 0)& Q* \$ F0 i; a, S. I; Z. p7 l# Z
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    + o: i! N' z0 W7 Z( ^+ w6 {3 c: A
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));5 ^7 E* M  h* r+ i) S: E7 `  E
  102.                             }' Y' i+ q" q$ B# z' ~% g
  103.                             else- k, a4 @  U3 p) ?7 Q
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));5 B- M& q2 M( x5 {/ k8 X' k

  105. - e/ `( y! I8 q( g$ c; j
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线# B6 A5 o3 W4 F) r/ v
  107.                             {: H1 X, T% x: z5 x+ X
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端! z# f( S3 m" Z; r8 b1 c& S
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)9 S" G) y5 ~4 J( j5 ]5 Q% Q
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);: g9 P: s) N. C" K* V
  111.                             }
    # ^+ L! f. x/ j% r6 I
  112.                             else5 P6 V: }* ^( G
  113.                             {& p) S2 V% j0 c' y
  114.                                 Task.Run(() =>
    ; x/ T3 \  m( W6 }/ P0 p! Z" p
  115.                                 {' I, d5 x+ k( D; k$ h" U# W
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    ' Z6 J5 B, U4 Z) k' |+ ]" D
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    3 y6 F- [& _$ p! M' I
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息+ ?0 w7 B9 Q: i2 y8 F4 J  ^1 Z
  119.                                 });
    & D1 ]1 v& z6 q
  120.                             }" R3 j; [1 `3 W: G7 M
  121.                         }
    + L: _; ?3 Z9 M2 Z, m- e
  122.                         catch (Exception exs)
    " D* m- e+ x+ `) {2 R6 E
  123.                         {. c; {4 g7 |* t6 \! Y0 r: ^
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    ! \5 L- N' R6 N( T
  125.                         }
    / K, i( h5 g1 N& j
  126.                         #endregion# Q6 g+ e* f4 p" u9 l# J
  127.                     }, u' A# Z/ I5 x% t
  128.                     else
    ) g: }0 {' V! ^4 i" Q6 w9 {  X
  129.                     {! v- E" h. E5 \! r- y2 Z& E; y" @
  130.                         break;
    & H/ ]8 V( H- N5 r+ ^4 c
  131.                     }+ C. s/ w9 p$ x- J
  132.                 }//while end
    ' w* F, ]* C: J; Y; `$ x; Y2 d
  133.             }% O4 `2 _5 F2 l
  134.             catch (Exception ex)* J/ C- b& r( e
  135.             {3 O7 x( Q, Y5 i  W, f2 j7 l6 g0 ~  ?
  136.                 //整体异常处理
    & Y4 H, h( W$ P! K  R5 F
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
      k3 _: {+ S' w
  138.             }
    # N" x' n) e2 F% v  x' b7 ?- T% |5 j- |
  139.         }
    5 p. S9 w4 G3 a
  140. & v0 ?4 o9 o: o! M& I' q
  141. ; A) @) c0 F) m/ h$ \' F7 J/ H) ^# ^
  142.         public bool IsReusable9 i' h" v9 |4 W  G
  143.         {
    , {  [' }  D+ |( S
  144.             get
    7 Q+ P6 X- B2 \0 e# K8 Y: \
  145.             {
    9 V% o9 Z1 x. ?) o9 l1 r1 [2 L) D, B
  146.                 return false;
      C- \+ Z  y& y- q
  147.             }
    ! K% S# M* E9 u: {0 f
  148.         }
    1 G: T% i8 S: ?5 B
  149.     }! E* }8 q$ I2 D$ g: ^# d
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
0 X+ X0 m/ }. m/ T0 f
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-4-30 20:50 , Processed in 0.066982 second(s), 23 queries .

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