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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
( G5 A$ O2 t% m2 b! y
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    3 ^6 G2 _6 [/ X0 U( s) A
  2. using System.Collections.Generic;& z: V) c. d: ^9 y8 B% O
  3. using System.Linq;
    & T  s0 V- c4 ?' `- K
  4. using System.Net.WebSockets;
    , g4 {& b3 C1 v: R4 J+ J% K; s
  5. using System.Text;
    1 J8 r4 j. [: }2 f
  6. using System.Threading;
    , d9 Y% o: _( N' v8 K, c7 }
  7. using System.Threading.Tasks;# T! h4 D  f9 l8 f6 e- F% g; j
  8. using System.Web;# ^6 U8 W5 N; ]" o8 e8 _
  9. using System.Web.WebSockets;
    7 q( y& i7 k) d9 o, ^* C9 _

  10. / k; j* A) y5 O8 d; `
  11. + q5 `' I& w8 C+ u
  12. namespace WebApplicationWebsocketHandler" R) c) u2 B' b3 f) {% ?# L  N2 @! f  N
  13. {
      u$ x! b* G7 ^* t; l
  14.     /// <summary>/ c  W1 e6 m8 d- L/ Z
  15.     /// 离线消息: c/ s) h9 \; y; B- F4 Y, D8 [# Q
  16.     /// </summary>$ o0 a8 @3 C# O, @0 e# Z% G1 S, O
  17.     public class MessageInfo
      l9 M0 P2 d# B* W7 z, u; d, B& R/ ^
  18.     {
    . c1 T7 t; F7 ]
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    9 l4 U9 w: J* {5 o7 z
  20.         {
    3 C+ l6 {9 L, |) R. J
  21.             MsgTime = _MsgTime;) k; |+ c( y# W
  22.             MsgContent = _MsgContent;2 A' S! S' j) S8 o0 A- M
  23.         }
    ( R, M; ~* V: G; @4 a5 ~8 B. U3 s! w
  24.         public DateTime MsgTime { get; set; }) A9 j4 }! D8 d) N% C, h
  25.         public ArraySegment<byte> MsgContent { get; set; }8 T' G2 g% E: ~
  26.     }2 D. R) I2 _5 q! \/ a/ s+ i6 y

  27. 4 G2 ]# J: ~! k2 y* Q
  28. 7 m8 r# L  N! I
  29. 0 {! a1 T' y  w0 W1 C( x) ], q
  30. & h& Q# m# i. X' j& f- g" x3 [( U
  31.     /// <summary>
    9 U8 X5 ?! i- K3 o* l. V0 x
  32.     /// Handler1 的摘要说明0 B+ P, c7 y( k& t& H$ g
  33.     /// </summary>
    6 `! u. A; J9 [! Y; t
  34.     public class Handler1 : IHttpHandler' Z: U. Z4 E8 N% s6 s
  35.     {
    7 c& M- ~+ R, V2 m! Y1 p8 `& [9 Y
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    & q/ j3 D2 P8 {( {/ ^; P, y
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池# H$ p9 q% ?/ M. K5 z) ^
  38.         public void ProcessRequest(HttpContext context)
    2 |! {; Z, J4 l9 b- a  b( @
  39.         {
    % x8 |3 k9 T; m+ t& [$ ?
  40.             //context.Response.ContentType = "text/plain";
    0 K% R8 m4 L, m2 u2 U) v, E7 Y
  41.             //context.Response.Write("Hello World");& ~. h, O5 r: I4 E/ x3 I: J: @- I
  42.             if (context.IsWebSocketRequest)
      `5 B( v& O! Q" s! r5 M( |. p6 S! F
  43.             {" ?) R- `* Q5 s' h
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    - s' u& Q$ i- c2 f) y2 N$ P
  45.             }
    5 K) y1 O8 U% G, H* h$ a
  46.         }& h/ W$ N0 E8 C  G+ e

  47. + Q  D! f8 o) v" ]* o" G" a
  48.         private async Task ProcessChat(AspNetWebSocketContext context)& t7 e0 r" Z/ H+ v8 `
  49.         {5 ^' S8 l+ c. C0 J1 N
  50.             WebSocket socket = context.WebSocket;3 \$ b$ W1 I& f8 I0 l  T
  51.             string user = context.QueryString["user"].ToString();. p; L2 Y+ _! ~( i% B
  52. " s. f+ Q7 a. m. ?
  53.             try% q2 Z- _/ M% y  u7 K3 Y
  54.             {
    2 B! Z7 Q/ Q% B' m9 V  a
  55.                 #region 用户添加连接池
    , y8 [. P! W3 a4 j' O
  56.                 //第一次open时,添加到连接池中' Y: I$ l0 M( R& k  N6 \$ J8 I
  57.                 if (!CONNECT_POOL.ContainsKey(user))  g4 r' _% N  r
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    0 l8 G* b) }9 T
  59.                 else
    4 X/ h5 D1 N# i* J3 F7 a0 `; q
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新: ~" g( m$ Q8 j+ n4 E2 i2 [& y3 G) H
  61.                         CONNECT_POOL[user] = socket;
    " e" x7 f, q( d6 B( Q) b6 f' A$ g
  62.                 #endregion
    # j$ G/ S6 \! {8 n2 `: S8 _
  63. ! a! C* r. H* I; `
  64.                 #region 离线消息处理
    5 n( ^. s  ]  K' r
  65.                 if (MESSAGE_POOL.ContainsKey(user)); W* i6 H2 Z) b0 m
  66.                 {
    7 W3 ?. Q" n- O0 m* d. R) x, x  p1 _
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];8 M. ~6 X% s1 Y1 U
  68.                     foreach (MessageInfo item in msgs)
      P$ V# }6 K0 A0 m( X5 v
  69.                     {* D7 D3 u1 K  u  b
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);; G, ~4 B) d& c* S$ m
  71.                     }0 i, L8 M; G* A& W
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    3 K7 k  h8 U1 d6 g( G) i
  73.                 }) o, Z' S4 l# ?7 ^$ C8 b2 o3 [
  74.                 #endregion! e9 I4 Q9 F+ Z. R9 A: j
  75. $ {" e) {7 u) s
  76.                 string descUser = string.Empty;//目的用户
    8 I1 A1 b" w$ I% F1 e. k* k
  77.                 while (true)8 y5 G/ n: G2 @' t. X% z3 `2 ?/ `
  78.                 {
    8 z. q& P$ K) n( u9 o; ?& t$ c) w
  79.                     if (socket.State == WebSocketState.Open)* H& }5 ^  H7 y: T; `
  80.                     {
    $ ~4 U# L1 H* L
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);: ^7 L) U( W+ I' m& L) |. i! N( e4 k
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);* V: r' G  D% q
  83. 7 t& _$ z6 C0 j5 C: s3 {( a, b
  84.                         #region 消息处理(字符截取、消息转发)$ D, Q: \, p# `: e. x) X0 c
  85.                         try
    - W! o& e- [/ _# ]7 V
  86.                         {
    4 l" X4 ]2 p% c$ F# f* c% Y4 U
  87.                             #region 关闭Socket处理,删除连接池
    , X: s/ H% g1 c6 t
  88.                             if (socket.State != WebSocketState.Open)//连接关闭) @& O2 u& Z2 K9 E. ]% l8 q
  89.                             {* d; C2 h; y4 d# E: V1 G
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池" X6 v7 m8 c; `" N/ }4 @+ a
  91.                                 break;" }: M) V6 C1 k7 C/ ?1 ?; G% L% {
  92.                             }
    ' O- ~4 `/ v  c  D1 R5 Y
  93.                             #endregion% t2 G/ M- n! {! }! g- j& P
  94. # t/ p% F8 o# R/ W1 O& B
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息7 ]/ f4 n# F6 }) j8 X
  96.                             string[] msgList = userMsg.Split('|');8 E9 u8 T: H) c" }
  97.                             if (msgList.Length == 2)
    / t3 n5 r, J) g
  98.                             {, s% w2 H6 ^: H7 j4 Q9 l
  99.                                 if (msgList[0].Trim().Length > 0)% F( w( f6 P! O
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户. s0 g9 S# J! t1 F1 r/ K# F0 R6 q8 ~
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));5 \* ]; N5 O) L4 v9 `6 q/ B- V
  102.                             }( l; n* T* l4 _
  103.                             else& z$ Q& M  G, y# s7 {$ U
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    4 Q7 s& B9 G! ?' L0 [
  105. % G* X, i3 P3 ?: v$ w
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    4 L/ O0 J$ [  G; F, K
  107.                             {# O% k1 I( V, E
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    2 T: J* P! {9 Y! J  F: M, S% z8 s
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    9 p" B# u1 x9 @7 A4 U1 L
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);- D3 q" G1 @4 m$ _* i0 p* r
  111.                             }
    5 R) B( _( O9 H4 D/ y; P
  112.                             else& ?& X. G- g1 ]  @, \# L+ B, O
  113.                             {
    3 @  D  X" l; }& {" j% N
  114.                                 Task.Run(() =>. q+ l0 C6 G7 j0 n* x
  115.                                 {
    * ], ?% |' p5 ]* [, v8 R
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    & C. L8 g; ^9 \+ ]
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    0 J- i* _4 [6 O' @7 s  s# n
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    $ U+ L, L! n$ U
  119.                                 });: I7 P9 s% c, e# V+ X8 ~6 p2 Q( A
  120.                             }* C: T" t  B, [* `& x' q
  121.                         }
    2 b1 {6 h. Q/ H! e3 s9 [4 O& z; @3 E2 q1 {
  122.                         catch (Exception exs)
    ( P; q0 l1 M0 F) F' c' `! J
  123.                         {
    3 m5 B6 e  z$ t6 o* E+ S) S  `
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    * R& r+ E/ D; r4 v+ D* l4 M: X
  125.                         }
    # n7 _* t/ l0 j8 G: |
  126.                         #endregion% z( ?! \; l# g9 F% z1 T
  127.                     }$ {6 k, J3 |* I  b$ ]0 I
  128.                     else
    % X  r4 o: `& c+ J* S
  129.                     {
    0 t8 V) S# ^, ?
  130.                         break;
    & b% q/ c" H1 A" C
  131.                     }4 ~0 [& |5 J" {+ [! O% q" o; t
  132.                 }//while end: A/ A- v' n5 w9 E# p; H* P$ R
  133.             }
    6 B  W  M0 C4 _" E+ |# [, R9 [  v
  134.             catch (Exception ex)5 O9 G9 Y; g! k2 H: t; g) i
  135.             {' K/ e% G) g, h$ @
  136.                 //整体异常处理' ?) d8 E" ~. q, i( z" m7 d) ]/ m$ g2 n
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    * B7 p1 L. V  P1 m! N) a- e
  138.             }
    ) i3 g, ~7 s: H, w
  139.         }
    2 k  [: I+ M; V9 i6 X

  140. * s5 B2 c* Q, R4 e! l; Z5 ?  {
  141.   i6 D5 G9 y* ]5 E
  142.         public bool IsReusable- o; _3 j* r* B$ S# S
  143.         {: U8 a5 m* ?& i0 y& J4 m2 j! ?
  144.             get: p1 @9 F7 Z& U) @7 A
  145.             {$ Y, ?4 O) B, s5 L& Z/ g  F
  146.                 return false;  v5 |3 q% g5 [
  147.             }
    + ]( ^, i7 b  z) z: M
  148.         }
    : M% Z+ Q) k0 Z3 x
  149.     }
    $ P' ^$ G/ O; [7 K
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

. I: s4 ?/ r, }/ |% v+ P
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-8-4 12:23 , Processed in 0.070060 second(s), 23 queries .

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