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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
0 E: U' Z; n) _2 o
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    ) z& y+ \' p! L
  2. using System.Collections.Generic;0 x7 B( `7 w2 z' E
  3. using System.Linq;7 l5 R  m& q, Z0 @  c  J; o0 C$ `$ ~
  4. using System.Net.WebSockets;  n, j$ z0 y% O) w; `
  5. using System.Text;
    8 F9 B6 R# k$ B6 K# X+ d
  6. using System.Threading;# Z& w, p$ |2 @
  7. using System.Threading.Tasks;& V9 i& I3 E! ^' x5 H+ B0 W/ A4 D' j
  8. using System.Web;" Q3 u0 k  R6 T9 ]
  9. using System.Web.WebSockets;& @; T5 U2 n9 N9 f9 e" D
  10. 6 n8 Q) R6 a" X; _7 x* o( b+ I; M
  11. 3 W3 D9 s8 U! u
  12. namespace WebApplicationWebsocketHandler/ v4 _* H& C" s# k. P
  13. {
    3 y1 T) m/ c' v9 V9 f0 \
  14.     /// <summary>. v& C* s( \) ]- ~( `! i
  15.     /// 离线消息
    2 S0 |: c) J( c# ^  o2 r" T
  16.     /// </summary>5 r( y& |+ V7 R/ F' o4 S
  17.     public class MessageInfo
    8 t7 L; y0 `4 J8 w( W# l" Y* N
  18.     {2 g3 s: H" G( y
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    ( g4 r, i" }& }2 F' @4 {
  20.         {# m" C6 D& w  \
  21.             MsgTime = _MsgTime;
    ( V$ ^! s- Z1 O6 A8 _' z( s
  22.             MsgContent = _MsgContent;- O. i  M2 Q  R
  23.         }# ^- v: k" L( C5 r# i* a
  24.         public DateTime MsgTime { get; set; }
    ; A% j' P- G2 v: F7 w6 O
  25.         public ArraySegment<byte> MsgContent { get; set; }) [4 O3 b* z) _% ?0 B
  26.     }
    4 a$ H/ @- {/ l9 B; F' }: ]

  27. 2 n- B1 c, |7 @2 p/ D; V
  28. ; P1 _9 m: n; M

  29. ( m" k2 O& U; l. N. v& [5 l
  30. % T1 [( Z* [. c' I: o
  31.     /// <summary>! y4 S1 u+ e4 T9 V) w$ y; {
  32.     /// Handler1 的摘要说明
    & n, V+ E6 X$ c; r
  33.     /// </summary>0 f3 _& o5 H( v* j- B1 P0 a
  34.     public class Handler1 : IHttpHandler' ?5 Y8 A2 a) c0 j  P5 K9 E7 c
  35.     {
    4 r! }( ?# L2 F# U6 H+ ~
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    9 Z5 `, ~' w& K. g) s" `7 k8 u# P1 I
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    7 [0 S5 x" z; N
  38.         public void ProcessRequest(HttpContext context)  U% H0 Q' G6 h- t$ |9 |
  39.         {
    6 l5 c8 u( \) z  H9 s6 ^
  40.             //context.Response.ContentType = "text/plain";  @; c; u* Q) \6 S( |/ I/ d2 E
  41.             //context.Response.Write("Hello World");3 d# B: T5 a$ e  j- Z$ J# }/ z4 l
  42.             if (context.IsWebSocketRequest)
    . p# d  Q* B( j
  43.             {
    * {0 ], ~! n9 o% o+ U2 m& P
  44.                 context.AcceptWebSocketRequest(ProcessChat);4 g) F: }" ?6 ?
  45.             }
    : E+ Y4 B( h+ W" m; ^9 `$ j6 {' o
  46.         }
    " O' ^# T7 L! N, _
  47. 3 ?7 G( {! Z  n  h3 U3 u
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    6 ]4 I& C0 L* S6 P* E
  49.         {4 d% s% O# N8 p  J
  50.             WebSocket socket = context.WebSocket;
    0 m: v" ?4 X2 G5 r8 K
  51.             string user = context.QueryString["user"].ToString();
    ! c0 d; b, f* y( C1 X9 r
  52. ! b/ l" w( F7 n$ [7 A6 G+ C! h+ _
  53.             try
    5 K  U' k5 a- t! a
  54.             {8 W! X7 N" u) D, v& G) H
  55.                 #region 用户添加连接池1 L( z( h" S, g. Y1 t/ s2 |8 ?& s, }
  56.                 //第一次open时,添加到连接池中
    & v$ S. W  d) m
  57.                 if (!CONNECT_POOL.ContainsKey(user))! b) N# ?/ g) {: {  [, S3 `. T
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    5 R/ m! l; L" j( H6 |% z
  59.                 else
    / O; Z/ [0 m* e( z* W
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    - n7 n. D9 c7 I4 b& I2 e9 E: s
  61.                         CONNECT_POOL[user] = socket;
    9 q8 Q/ A) Y9 O0 ?' Y7 Z
  62.                 #endregion
    8 U1 Y3 F, H; H. V/ ^2 R3 s

  63. 1 k' J- F5 k4 H* @! [; G7 u5 P0 ~
  64.                 #region 离线消息处理/ H# \) Y; n. g: ]; _& g
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    1 {0 l) m! \# R, y) j& z
  66.                 {
    * t% k) b2 O( E5 P1 z# O' b
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    0 k9 G: l2 o' d$ r3 S$ n" r
  68.                     foreach (MessageInfo item in msgs)
    " U$ C/ D$ b8 d2 t5 R
  69.                     {
    5 B  o7 o) F( Y6 g, `$ Y$ _0 I
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    9 [6 L! [% h0 c% s3 d
  71.                     }
    $ X3 U7 @  i* ~5 W1 a
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    ! b& C4 w- g; h3 V$ D* D$ N, t& Z
  73.                 }
    , G0 ~( P7 k5 F9 S2 E8 f7 j
  74.                 #endregion7 V$ e3 u& @+ M& F
  75. ; M5 I% O& o( K; J3 B1 e
  76.                 string descUser = string.Empty;//目的用户6 m7 b: a2 G* \
  77.                 while (true)
    ! j, t! `7 v$ d' p
  78.                 {7 y) Z1 z: o$ B' d/ \# T5 R
  79.                     if (socket.State == WebSocketState.Open)
    + t# B  d, K7 D/ H1 I
  80.                     {' D" S' L! l6 M/ Z3 M
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    ' w! \, W+ [* H2 \6 w
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);: o2 }1 E# j- T: S) ]

  83. 5 j( C  I  B4 N  ^  i  k# V/ z/ R6 d
  84.                         #region 消息处理(字符截取、消息转发)! F5 f1 `3 U% J7 W% w) C. z
  85.                         try
    ' l. p" v8 C; P5 `1 y  }
  86.                         {6 r$ @' A( ]" {; K7 s/ f8 W* r; V& j
  87.                             #region 关闭Socket处理,删除连接池
    / ^5 J8 r) J4 B! U$ _2 L( ^- t
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    3 E  a: N& ]8 W; u8 K8 }0 `8 F; y
  89.                             {; |9 m$ X6 _4 h/ F) r0 ]4 h0 v9 b8 D
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    ( Z0 f; ^2 _! L* V, g% Q
  91.                                 break;& ~- v6 e% G" X" c( r
  92.                             }0 E" {7 p+ T) ?; }
  93.                             #endregion" V6 |+ {5 z! w+ U

  94. 3 a3 A; p8 Q# Q3 c3 v" G
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息0 E+ S( [% O$ Q% F) |
  96.                             string[] msgList = userMsg.Split('|');& {; L& {% L4 T
  97.                             if (msgList.Length == 2)1 \0 t' b: g4 F( q
  98.                             {( x/ ]" Q$ K. k6 Y  Y
  99.                                 if (msgList[0].Trim().Length > 0)2 \0 X' c8 _' W" V$ K
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户) K3 a  |: ^$ ?* _% S- E
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    * ]9 l1 G9 A; `* Z
  102.                             }
    , w  @1 S0 {# |- q8 O) n6 f, \
  103.                             else
    , F! h/ S; x( n
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));6 d% S2 w( n$ i8 ]7 I/ ^7 d
  105. ' B' Y& [, n& a5 ?" N( I
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    , |! V0 w- a% ]
  107.                             {
    3 ^6 G4 ]2 @4 r  u4 a
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端* z, m3 ?) Q* h" d' u  F
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)  `/ K: |& o$ w
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);( n7 V- p, G0 I$ y6 ?# F6 ]
  111.                             }
    + |" V8 c' e- c+ d+ \
  112.                             else% E$ R6 J# Q5 i" X8 ^+ I
  113.                             {
    * w" y$ M+ _8 {8 p! P; w/ g" m
  114.                                 Task.Run(() =>
    6 }; @2 b6 e( o+ A4 d5 r
  115.                                 {
    * o6 U# `) e! |; F8 p0 B
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    : z# E  g* C, W; E# g$ m
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());1 L4 o/ ~+ a' d
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
      C6 D  M; C/ G; Y2 G9 v
  119.                                 });
    7 M1 m/ l1 v$ S
  120.                             }
    9 s; E& t) |7 Y: X( U
  121.                         }
    4 A' w# d7 r. w7 A1 F. c: ?2 n
  122.                         catch (Exception exs), X( ^, h% N/ H. N
  123.                         {
    ( k/ ]# N2 v  ], v" B
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息5 ~' k' N* b' O) {. Q, d' u9 r
  125.                         }8 J+ ?: `7 M: C/ q! k, x4 |
  126.                         #endregion  X" b' u$ {* Y* q, b, y
  127.                     }6 s8 D6 z+ p- n- m+ s% i
  128.                     else7 I$ I. {  G1 I- r% C5 O( o
  129.                     {4 F2 h7 _, m/ j6 o4 h# E
  130.                         break;5 i+ I7 c1 l4 `# e9 R
  131.                     }5 R& X& j, K" T  H4 Q
  132.                 }//while end0 V, m0 f- P: X5 t0 G
  133.             }
    ( x$ n& x5 G, ]: n- s
  134.             catch (Exception ex)  x( }+ `) p2 H' u$ ^& P
  135.             {9 f- S; W- M7 Q0 o* x
  136.                 //整体异常处理
    9 R, v4 t+ i2 b! D3 I! ^
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);* U' a/ ]: U, v3 T& F/ q$ r
  138.             }9 S7 j) i0 ]* v* K( n6 ]7 A
  139.         }9 Y) @. T. {& l  @

  140. ) ~: X! g1 Q0 j5 F- p

  141. 8 Y0 u' e+ ?, g( u, i+ f$ b/ Z
  142.         public bool IsReusable
    1 @! K; ]+ O3 ^- m# O
  143.         {
    ) \  h* w7 }5 F' @, I& @
  144.             get) f- o8 t: e4 @- L
  145.             {
    ) Q/ O9 ^2 N5 T0 F
  146.                 return false;
    2 f5 M' C! k' U& U- i6 q& ~6 t
  147.             }4 }/ {) v. L* C: ^! q
  148.         }
    0 v# K6 K9 q# J' x/ f
  149.     }
    ; u1 Z1 O: M* a, g7 n7 }$ A+ z
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

0 ^+ Q) e# @( _+ Z
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-5-2 17:36 , Processed in 0.085678 second(s), 23 queries .

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