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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
! \* z  @! V0 K, i4 h
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    $ H2 c# u, p5 E; s
  2. using System.Collections.Generic;
      Y' K9 \+ V0 }1 _1 o! t5 q
  3. using System.Linq;$ u% a: h7 ]4 `# y
  4. using System.Net.WebSockets;' a- v3 b3 ?' a# G
  5. using System.Text;$ S- I0 j6 c( \6 Y4 a
  6. using System.Threading;/ e/ w5 W7 s1 h  v6 f0 x
  7. using System.Threading.Tasks;4 K' T' c& r; e$ q+ R0 F
  8. using System.Web;
    / I: K, K3 f: q3 u4 p; K/ d6 X
  9. using System.Web.WebSockets;
    # P# i6 E  U: Z7 `3 Q) A

  10. 3 C' a: K8 X$ |7 j7 _" x

  11. & r! o6 Q  @* X- c/ C' J" Y' W
  12. namespace WebApplicationWebsocketHandler% y# [2 n# T! ?1 a
  13. {
    7 h$ K- f1 d. `* D( }# A
  14.     /// <summary>
    / L, H5 q7 t; _8 |* ^& I7 P
  15.     /// 离线消息' I9 f) W, o, t# H) C3 m6 ]9 j" Q
  16.     /// </summary>8 o3 {2 u# H/ m: }1 Q9 Q) {6 g
  17.     public class MessageInfo
    ; {& N1 Z7 P  A& o) Y% w
  18.     {
    6 `, ]+ ]2 U  k4 g7 ?" u
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)9 o1 m- @+ Y* ~1 I4 }2 A
  20.         {- A$ r3 [+ A. B! J
  21.             MsgTime = _MsgTime;/ a# s& `0 s9 b8 ], M
  22.             MsgContent = _MsgContent;- J, z, P: y4 _- S2 A4 ^
  23.         }
    * n4 ]( u. r  R/ \1 H* m7 {1 P$ z' q- S
  24.         public DateTime MsgTime { get; set; }
    / A+ W$ ]9 {- |" K) [/ V! k% l
  25.         public ArraySegment<byte> MsgContent { get; set; }
    : f( b; r* D' Z, N  I6 V# |% H
  26.     }/ L3 J' ?" i/ ]& O/ p: O, ~

  27. ; P* D- K" S9 W- r5 p$ p
  28. $ P/ O% M* X& U6 D
  29. 3 A! Z( j+ Z4 s. y/ e; Q6 X
  30. / c* q' U1 H+ j, W6 i7 Q! n0 ?- _
  31.     /// <summary>
    ; K5 G0 e3 _- ~
  32.     /// Handler1 的摘要说明2 [" J) B. ^1 d+ {5 Y! f/ j' H
  33.     /// </summary>6 Z# q- O0 x5 b; b
  34.     public class Handler1 : IHttpHandler
    ( c) u8 O. W' T1 n
  35.     {
      J8 s0 W. Y6 c! u% }
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    ! p! u8 o  M( ^) C& K
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    , u0 N( y2 N6 D0 m% a  _
  38.         public void ProcessRequest(HttpContext context)& }# d7 I5 l: C& f  V
  39.         {
      G$ y4 u/ i. p  F! K' X" h
  40.             //context.Response.ContentType = "text/plain";3 e) v& h& T5 d$ w- |8 \$ g
  41.             //context.Response.Write("Hello World");
    ' y6 C/ y2 i6 W$ j, n) n( @
  42.             if (context.IsWebSocketRequest)
    : X1 k* y7 H% Q+ @* ]
  43.             {* \  @5 y4 W7 o/ s/ h
  44.                 context.AcceptWebSocketRequest(ProcessChat);3 v5 S/ ~" q5 z( P& N7 Y
  45.             } " j9 ~, X, K" `9 E2 r0 Y, @, g
  46.         }
    5 H) f9 n! q1 L. u

  47. 7 U' a" K7 F) o) k5 N  [
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    ( E6 i6 R( u3 S
  49.         {+ N" P4 a9 P1 k# P5 z; N5 o
  50.             WebSocket socket = context.WebSocket;' z8 y$ E: l7 y9 b! Q2 D* {
  51.             string user = context.QueryString["user"].ToString();- D) L  y* c% X5 T7 q6 a! e' w( V

  52. 7 q* C: k+ m8 K* I3 H
  53.             try9 J! {. \. J8 n" n1 q0 A- i
  54.             {
    - s. Y, ^0 ~% s7 T/ N
  55.                 #region 用户添加连接池6 W. m, s# T% B( Y. t7 ]
  56.                 //第一次open时,添加到连接池中! B, Q) U1 q3 E. i% Y
  57.                 if (!CONNECT_POOL.ContainsKey(user))" L, k5 _9 G6 |, M9 u! \+ \
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加! O) |: U+ @% l  l* i0 U0 c9 i
  59.                 else
    % m0 l- W7 |* r7 a& o; V
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新; U8 r& [% a% k" u* E4 T/ A; n8 e
  61.                         CONNECT_POOL[user] = socket;/ q8 g9 j7 E% h
  62.                 #endregion
    " w: U3 _& L' g+ n. K1 K

  63. $ U% y, A+ x2 _/ r" C
  64.                 #region 离线消息处理
    4 i  e3 x& n7 I- M
  65.                 if (MESSAGE_POOL.ContainsKey(user))1 @/ w6 t8 _$ t# u; _+ r4 N$ @% j
  66.                 {
    : i8 w) n! v, L- m; H  K
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    . d0 k0 s$ s0 o. j" W: b
  68.                     foreach (MessageInfo item in msgs)' Z8 K0 d, s  @1 E
  69.                     {$ V) i1 \5 n; s; Z& N- y/ q
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);3 i" E: r" F5 S. O2 ?$ _7 B
  71.                     }( `; p6 h. j. G' p
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    $ c% B( {0 t% Y! }
  73.                 }& b" J( A' X. E, A! p
  74.                 #endregion3 N" H% h4 w5 u1 r8 p+ z

  75. & B9 x0 ?% }' \) T( q
  76.                 string descUser = string.Empty;//目的用户( i3 m' W- [% T9 k6 b2 R
  77.                 while (true)/ h& m0 r# M- b, M
  78.                 {
    6 L) h! i7 _, |3 T: g4 V7 V
  79.                     if (socket.State == WebSocketState.Open)
    7 D. p8 f+ \5 y' \
  80.                     {
    % s& N- V; ]! L+ E! ^
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);+ {: d2 Y4 S' L( O) o
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
      _; |: J( G4 m

  83. , T/ u; q0 [7 Y/ w. l/ W' w
  84.                         #region 消息处理(字符截取、消息转发)- c' N7 t; }6 r& D
  85.                         try
    4 j+ O% v4 O: T7 \
  86.                         {
    * `* S, D5 j( R+ V
  87.                             #region 关闭Socket处理,删除连接池
    # ~% o# I% h% Y* [, z
  88.                             if (socket.State != WebSocketState.Open)//连接关闭2 z- J) k/ d# Y  }4 x/ e, z
  89.                             {
    - G( ]" y- Y8 _: p& s9 c
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    " M$ W0 Z9 y" J. x7 j  c9 `: [* T3 R
  91.                                 break;
    1 R9 B4 C# l% T
  92.                             }4 p6 M) Y2 C" |8 s5 Y5 ^- g5 v# Z
  93.                             #endregion
      U! E& K0 z( I
  94.   h6 @8 }7 X6 P7 v
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    0 c" u0 y4 t# h& R$ V
  96.                             string[] msgList = userMsg.Split('|');
    ; N" @9 q7 {7 S! {
  97.                             if (msgList.Length == 2), x% M9 n; V9 O9 @0 j% X* y- E
  98.                             {
    6 r! G" E* i* _/ x" k% M
  99.                                 if (msgList[0].Trim().Length > 0)* ?& P" ]! h0 b
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户3 H, t9 ^1 N5 m$ r3 l0 a5 A
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    & O2 S3 A% O8 i
  102.                             }
    & A" a; e" j( E( a# j
  103.                             else
    6 S3 O/ D6 H& U. L# Y
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    % a- D, {0 S/ {+ }

  105. ' n4 X4 a/ q4 I9 k3 J9 U
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    ) S" f, Q( U) o% q# \+ B/ U5 _' N/ D
  107.                             {0 E2 \& v+ a3 T1 I; a
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端. a3 Q0 U- X* p; o5 d9 y, `
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)+ N: ~- h( K% b/ k3 V+ F
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    2 K* V5 ~# i- @4 j# }
  111.                             }3 n9 K  r; x- j5 l( a
  112.                             else
    , j+ q" d1 O  B) M( D1 `
  113.                             {
    & d. }. [! M. Q
  114.                                 Task.Run(() =>$ r/ t4 |2 ?5 u2 J( t0 S
  115.                                 {& o% i2 y4 [! X6 E! o) C" z
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    & Q7 e8 {; ]6 k, f0 \
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    : J1 O$ ~0 X5 C. }% K
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    ! f) |5 g/ \2 O: @9 I, x
  119.                                 });
    7 O( Z; {6 c7 {3 @
  120.                             }& {  q" e2 |9 Q% i  i) }+ T. Q) I
  121.                         }
    7 d7 u7 r7 c1 t( s1 X
  122.                         catch (Exception exs)
    3 o$ M' I1 y+ O! e7 h1 z5 B
  123.                         {! U9 D! a3 J& E7 E
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息1 P; o( S7 N$ i  K$ u
  125.                         }9 {  s! p. g" j( Z+ b
  126.                         #endregion, ]& I6 W$ e! z. {' @
  127.                     }2 W" j% n. G! ]* K; S
  128.                     else
    ( t. s+ Y2 d$ d8 [4 ~/ a
  129.                     {
    , c4 Z3 o: m) D
  130.                         break;1 ?, R7 K" X/ E% e+ U
  131.                     }1 a" r* j6 ~  A7 b, \! N" Z+ j
  132.                 }//while end
    & E& _0 Z  E, B( C( A
  133.             }
    ; I; s5 I2 q! W, t5 G, {
  134.             catch (Exception ex)# z% I/ b/ v: {. ^8 o/ r
  135.             {7 Y  C; s# A8 @2 M6 q2 \1 e' d$ S
  136.                 //整体异常处理3 D* R4 ^" s- x4 w# D
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    * V2 A: I8 ^: f
  138.             }
    & x5 R  r! ^/ D( ^2 v  o; o
  139.         }
    : N/ X- K- _/ K5 c# C

  140. - }( C" r1 k" J2 I5 C# j

  141. . Q& E5 S! _0 M$ V  _2 F0 n
  142.         public bool IsReusable
    & Q  ?, c& g! h) F) _- z" Q8 h$ O
  143.         {5 t" i6 n# ?) f* j
  144.             get
    # C: h+ w+ r2 ~2 y- b7 k% d( h
  145.             {0 l/ L$ t( F1 T. ~& Z7 h
  146.                 return false;( ?! L; g8 k& n3 L2 E
  147.             }
    9 F$ b. ^  N0 u7 q
  148.         }
    : o1 ?1 A+ a" L1 p, t9 M
  149.     }+ S$ m9 ^/ I+ h
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
1 C6 D) t+ @) b, _$ K" V8 a/ }
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-6-20 02:58 , Processed in 0.056254 second(s), 23 queries .

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