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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
* x0 o" M0 B5 p4 Y- r3 J3 r" K* X
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;) H" i' d; `# y( E% `
  2. using System.Collections.Generic;8 G; C& y. f7 U5 H
  3. using System.Linq;
    . C7 a3 n* _' \* i" I- ?: C
  4. using System.Net.WebSockets;
    7 Q5 q' e. h# S. Y4 u/ `( c6 Z
  5. using System.Text;
    & d0 c* L4 Z$ ?1 L( S
  6. using System.Threading;
    , V" k/ Q4 O, P, ]9 U
  7. using System.Threading.Tasks;
    ' `9 Y  g% P- {1 l1 A
  8. using System.Web;
    1 ^3 M# ^% Y- _6 B& u  T
  9. using System.Web.WebSockets;
      N+ i, X, o+ C7 }
  10. ( b- @1 A8 ?' T2 K( V  e2 f6 t

  11. + z/ R  U/ x: v% Z- {8 K
  12. namespace WebApplicationWebsocketHandler9 N& h  X  U/ o7 |
  13. {
    ; S% R& p+ l' f* C7 P4 `
  14.     /// <summary>
    * T0 E0 n9 |" ]; N; Y
  15.     /// 离线消息( @7 A, ?, q; o1 J
  16.     /// </summary>9 Z5 \- y/ J3 ~! q
  17.     public class MessageInfo
    & Z6 r6 ]& p% D1 v
  18.     {
    + ?& L) j0 D$ I2 S2 d" j+ ^
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    ( M& k' d5 u6 K. Z8 q- c# l9 F) p( t  k
  20.         {
    8 g3 n5 L% H% l9 Q) }8 M# ^0 W
  21.             MsgTime = _MsgTime;
    % K9 ~3 z' |$ x3 ]- Z
  22.             MsgContent = _MsgContent;% g% F+ I8 s6 I- ]
  23.         }
    8 e- Y5 U% \: G* H$ ^: y" O. T
  24.         public DateTime MsgTime { get; set; }5 r3 f0 b& X/ l' X# y
  25.         public ArraySegment<byte> MsgContent { get; set; }
    & H, t6 ^0 O0 N( j
  26.     }  O. s. m! U# w9 D4 i, O8 m/ ~, f  P& q

  27. 2 `  u$ i! @  J+ I$ M! s! n
  28. 5 {0 w# j8 Q/ c1 m" H. T, e+ E' n

  29. / O" b" U  a4 D, d& f

  30. 4 x1 ?4 a0 V/ u# j
  31.     /// <summary>
    & ?9 P( X9 F$ r4 w
  32.     /// Handler1 的摘要说明% {7 W6 y2 F, g5 Q. o
  33.     /// </summary>
      p. F/ R2 r: z' ?+ ~
  34.     public class Handler1 : IHttpHandler2 p: Y! s6 [' ^$ q8 x& [! v) ]
  35.     {: v2 x: I& H, Z, W2 L7 P
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    5 p3 f5 }$ j& _: E
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    2 G$ q  h, }! p3 x. R: P, v3 R
  38.         public void ProcessRequest(HttpContext context)2 u2 h6 L0 q, n, v1 }1 L4 A
  39.         {
    " k* J3 U) |2 t' |0 G
  40.             //context.Response.ContentType = "text/plain";. P$ i9 K1 G/ R4 k
  41.             //context.Response.Write("Hello World");! [" e& }7 I# B2 h- e" L, @
  42.             if (context.IsWebSocketRequest)4 D! D$ Q9 T! {+ T0 ?* U" m4 A: _& r
  43.             {' A+ j" `6 }# `/ ]/ @4 t7 a" k6 y
  44.                 context.AcceptWebSocketRequest(ProcessChat);+ a5 b7 _& B3 o9 c+ y+ m2 d
  45.             }
    3 g3 j1 x( c+ X
  46.         }' Y3 ~+ o) o% r% n9 k

  47. * ^6 z2 y# l8 Y& i
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    # Y, p; m* V! O6 R: @- v
  49.         {, Y1 i; B0 l. m/ |2 W7 [. i
  50.             WebSocket socket = context.WebSocket;
    1 G0 x! a1 q: S; r
  51.             string user = context.QueryString["user"].ToString();  x- N) I+ R' m( ]& y- K$ x

  52. - G' q3 P0 X3 j$ n" T
  53.             try
    4 u# U( H  S& Z$ h, I  B
  54.             {
    1 J6 R: [" s* b1 F0 h
  55.                 #region 用户添加连接池
    ( ^* B' y) K; j+ q- Y
  56.                 //第一次open时,添加到连接池中& _2 Z# [" @0 j& Q- l2 M0 E) U
  57.                 if (!CONNECT_POOL.ContainsKey(user))( L4 V. l1 @" o% j3 a. z
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    . z: L! f" C' c( o) T1 I' \+ A0 u
  59.                 else( Z( T/ B  G  S9 |
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新8 z+ q5 k3 G3 C) F4 I2 s
  61.                         CONNECT_POOL[user] = socket;  _1 Y1 |% S6 q8 l: I7 v$ }7 ]
  62.                 #endregion
    # v) F5 ?+ s; O, K

  63. ( m4 Q- w; U5 R2 g- L
  64.                 #region 离线消息处理
    0 m+ W2 T; W9 z) `: P6 t3 ?
  65.                 if (MESSAGE_POOL.ContainsKey(user)); K. T6 ]  v. }
  66.                 {
    6 ?8 s- U. N1 W# x
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    7 L) B' u) A( `0 Z
  68.                     foreach (MessageInfo item in msgs)
    & w8 p. }' S9 o( |; R
  69.                     {* H" Z4 x; H6 s
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);! E' r2 @: g" X! c
  71.                     }
    6 z5 A# }& F0 @2 ^
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    1 @) }' T- O4 w. i% \
  73.                 }% v5 C  `; P7 Q0 }1 @% R
  74.                 #endregion
    6 j7 I' Q0 D/ p1 x3 q1 E3 j
  75. * h( E3 e1 t) E- f( D, |, s
  76.                 string descUser = string.Empty;//目的用户. _8 M" f9 U. K: |% e
  77.                 while (true)
    ) b5 r7 j- u3 r$ H( |
  78.                 {  q# y3 L! L! ]* f* h
  79.                     if (socket.State == WebSocketState.Open)
    0 B( f- A9 C- B# ]
  80.                     {
    1 T0 o+ K! x0 @9 a  P( d" h
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    , P1 l/ f2 v9 l# c: o6 F$ T: P- P3 o
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    8 ^2 o4 a8 L) k

  83. : A: f  I5 S+ V
  84.                         #region 消息处理(字符截取、消息转发)1 m3 }$ `- ~% o4 s& \: K3 L
  85.                         try
    ; J# C( E; H" O7 L
  86.                         {, |" X  T  W2 e7 t! Z2 h
  87.                             #region 关闭Socket处理,删除连接池2 R# X6 {9 l! Z9 D
  88.                             if (socket.State != WebSocketState.Open)//连接关闭, v! P: t- R0 ^. ?+ ]. S  j
  89.                             {! a2 f6 t- c. B
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池- a& L: s+ Z8 w1 c; x6 }5 i
  91.                                 break;9 [3 P0 g4 B- U; {
  92.                             }
    % Y% {* m2 L0 g% T; C2 }  T9 c
  93.                             #endregion, C: R& {7 G: K, U

  94. : X: }1 g4 M' b7 Z$ W
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    1 U2 i$ j1 p( R8 r6 g9 ]# C' C
  96.                             string[] msgList = userMsg.Split('|');; n% f7 N$ g6 H9 g0 @# a& r4 J
  97.                             if (msgList.Length == 2)
    9 W0 r" L0 X( f; c' A- M
  98.                             {
    2 g9 d5 \+ C- ~7 ]0 B5 y  D! G9 }
  99.                                 if (msgList[0].Trim().Length > 0)/ P$ w  Y4 l8 A
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户9 w8 b0 d, P$ ~
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    ) i2 |, S3 n1 B4 c9 ~- `' u2 s
  102.                             }( l$ l- B+ A" {+ H
  103.                             else
    , M( `& N4 |; ^. t) u3 D9 K
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    7 y4 a, P* r( E7 p
  105. * B8 S' F0 {- r. I$ S' i
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线1 ^) V8 j9 E7 H
  107.                             {( Z. u% H1 h; ?# u# k& u1 f2 _5 S
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    5 n8 G4 Q) v# {( }  B
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open). V) B' i: J/ x3 S  ~
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    7 `% R2 S2 r. ?( L" I( N+ I
  111.                             }
    ' O8 g4 \" @; ~0 M$ g% C5 J, |
  112.                             else
    3 l" @% ]: |- {- M+ a; H
  113.                             {
    2 m, T: f9 \; C) x0 n1 ^+ z
  114.                                 Task.Run(() =>
    2 v- Z& d9 W6 N' e1 {8 [% W
  115.                                 {1 t' `! B6 x6 j+ r8 C6 ?
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中% r" d7 J% l1 o: N% n; S" U. I
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    6 g  ~. v4 v# _! N  a5 C: L
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息* m/ x; H5 ^, |. n, V& E
  119.                                 });# o8 c: s1 I( }8 x* D
  120.                             }
    7 o6 J' u$ O8 J/ ?1 T+ G% V" A
  121.                         }
    4 I  h/ b6 {; U" S
  122.                         catch (Exception exs)- G8 Y% s" H" |
  123.                         {
    + S) q+ D. L! ^1 q2 `$ B. c
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    : C8 E6 i9 g0 M5 W4 w
  125.                         }, q  p6 k0 j2 p6 y6 v
  126.                         #endregion
    2 y+ X3 u  Z( l
  127.                     }# N( V/ I* l/ r( _1 J
  128.                     else
    + S; I5 [- j& v1 v$ I" Y0 D$ T
  129.                     {
    7 U* n7 I% x0 F1 r. ?0 H1 M. ~( \
  130.                         break;( R# ~: ~, k4 E3 |- D& `1 ^/ g' Z
  131.                     }" H2 V3 T9 E( I5 C% i( O, Y+ A
  132.                 }//while end3 [" k* q  z/ s+ K1 a
  133.             }1 o% P6 E! F6 R
  134.             catch (Exception ex)
    . [  p* Y' g5 \0 |2 x  v! c
  135.             {, g0 m8 a9 t$ Y' f- g7 N
  136.                 //整体异常处理2 I5 S+ @# Q! F5 w, o2 T) Z/ W
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);( l1 r, R: q0 R% E# o, z3 H9 d7 @
  138.             }4 h% P! V$ E7 i5 y( j+ E( L
  139.         }
    3 K6 Y- g( Z" x+ K: I
  140. % M8 N" G7 P. T. ]" @" e

  141. ! k; W7 l. u( c. _; ?
  142.         public bool IsReusable
    0 N/ r! I- }8 b
  143.         {$ d$ l0 R" P. y$ u0 f) `  E7 `& k) N* T
  144.             get
    7 F2 @/ d( ]" l  s0 {
  145.             {' b3 d4 D0 F" O; I* N
  146.                 return false;
    9 G/ X3 S( F6 I! d/ N
  147.             }' C+ R: Q1 p6 u- H8 J- G: y
  148.         }
    6 R1 m9 O8 v: Q  i" z% F3 g
  149.     }
    , N  o7 W. Q, K9 N# p
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
2 z" U2 f, q" _: K# H; R
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-1-30 18:44 , Processed in 0.060446 second(s), 24 queries .

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