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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 显示全部楼层 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
5 m; p6 q2 U& m4 ^/ ~! x
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    ( M3 S$ i7 F; X8 C5 p# k2 P1 v+ `
  2. using System.Collections.Generic;
    & L' P+ I: P! x( Z$ w3 w2 m8 M3 T
  3. using System.Linq;
    $ t0 a4 P1 t. K8 L8 }, Z
  4. using System.Net.WebSockets;/ G9 \& y% L9 I1 l
  5. using System.Text;
    ' T+ i3 N+ y  |0 m. n& |/ [* w* ^' L
  6. using System.Threading;
    ' E! ~' K. R; d- X& X: U
  7. using System.Threading.Tasks;
    + g' ~0 C: ]0 g! r
  8. using System.Web;
    # l0 B3 N. I' p( x" C
  9. using System.Web.WebSockets;' g, U/ `; @: g: @) R
  10.   n2 y/ K5 n" A# _
  11. , v& i8 c! E7 J. I
  12. namespace WebApplicationWebsocketHandler
    ( o) J% E, c9 }# k2 Z) _
  13. {
    " _' @0 f8 Z+ ^- v% @6 h3 V
  14.     /// <summary>: G. U2 B4 M+ E. l& |2 @
  15.     /// 离线消息
    * g5 h4 s) {7 d* N6 M. I8 R$ x
  16.     /// </summary>( {% ^+ f: y2 s4 g9 u( Q3 e% _
  17.     public class MessageInfo
    2 _0 c( o/ I0 K
  18.     {
      o: ?/ k6 V8 T6 x
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    0 Y# s! c, A$ @
  20.         {
    0 `# \& m5 k, M3 V
  21.             MsgTime = _MsgTime;
    6 h0 O0 y5 F: y* X
  22.             MsgContent = _MsgContent;
    & q5 Y$ |5 N- l# t- F
  23.         }$ I5 Y( F3 n' y
  24.         public DateTime MsgTime { get; set; }; F, \+ z- L' V) G* g
  25.         public ArraySegment<byte> MsgContent { get; set; }0 U9 @$ L- ?/ Q
  26.     }9 B# F! B! }6 L& ?
  27. % I" {" P  Z5 B: W

  28. + N8 M% M3 P  n( O" P( o- @0 b

  29. ) A" x  o# w$ F/ X1 ?1 H  B( p
  30. 6 y2 j1 ?/ a* C2 Q, o- _7 w; C6 c
  31.     /// <summary>4 e' b2 H& H  r' Z& ]4 ~9 ?
  32.     /// Handler1 的摘要说明
    + O; r1 O4 T/ x3 V$ t( |& l! x. m+ m
  33.     /// </summary>) U' E* }+ k+ E& C, Z
  34.     public class Handler1 : IHttpHandler
    . g" V* ^7 O) z% w$ v$ |
  35.     {
    * u! n+ d4 `; D2 a7 M
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    - {* |/ p, ^# x
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    6 w  y( }: B+ W
  38.         public void ProcessRequest(HttpContext context)
    , F6 `( f& r; |0 l1 T
  39.         {
    4 s% g0 _6 b  s5 ~
  40.             //context.Response.ContentType = "text/plain";
    ; N- d7 ?7 E3 R  Q- Z9 C
  41.             //context.Response.Write("Hello World");, |: j  T- G# J  d  o7 o
  42.             if (context.IsWebSocketRequest)7 C. w  P& t! K, M. P  f
  43.             {+ \+ G: R) n' I6 W* Z) q
  44.                 context.AcceptWebSocketRequest(ProcessChat);8 h2 Q7 X, P9 n# C5 d8 _2 W
  45.             }
    ( C0 e/ N& d8 D, o& G# P
  46.         }/ t" V0 x( z1 ?; {: d4 C

  47. " h$ s7 d8 i1 _) X4 {) G
  48.         private async Task ProcessChat(AspNetWebSocketContext context)0 t# e2 N5 d6 y* L
  49.         {
    + g6 W; H' B) l0 }! Y& k
  50.             WebSocket socket = context.WebSocket;
    3 q1 N7 g; m+ k' W) c" R3 Z
  51.             string user = context.QueryString["user"].ToString();
    , n# F) F) c4 J7 z6 T

  52. , N% Z+ T7 H7 E# y% I% X/ k# c
  53.             try; ^* f4 f: U7 C5 D5 A
  54.             {0 O) t; x' O: ]$ n# Y- j: `
  55.                 #region 用户添加连接池
    - a& a: B! T( D  @/ u0 Y( ^& l+ C1 O
  56.                 //第一次open时,添加到连接池中' ?4 Z6 W7 L8 H7 C5 b& R
  57.                 if (!CONNECT_POOL.ContainsKey(user))8 ?6 k% b2 |, m9 q- v
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    4 \0 f8 e1 k5 y! d& |8 t* {
  59.                 else4 V" `. [! T; ]' U! J5 {% }
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新9 |3 g( e3 P9 I& }
  61.                         CONNECT_POOL[user] = socket;
    5 u, J  a1 \9 _6 u0 U
  62.                 #endregion6 q! k+ A* x, o! N
  63.   j. I0 P# P# @; g7 E& ^7 \
  64.                 #region 离线消息处理
    ' K8 U6 z" I  t5 s# c7 h
  65.                 if (MESSAGE_POOL.ContainsKey(user))# g  T- c9 d% R+ w* |6 }
  66.                 {/ p" r+ v  d! U6 E) @1 r9 l! b
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];) e( f9 X3 h5 s) ?7 G# x' j
  68.                     foreach (MessageInfo item in msgs)1 R. }- e) x$ H7 t" r/ ?; E% a: K0 p) S
  69.                     {& s, o; U2 H( [" I
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);4 [, Q5 s4 C* O. w: \
  71.                     }
    - S. U2 z% T; c& ^
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息; }/ y+ E. n2 n
  73.                 }
    4 N; m1 f0 t" y6 h. D
  74.                 #endregion
    5 t, u+ Y) d$ u$ r) V0 F6 l, O! t
  75. 4 W1 m/ c# M+ |8 s; n2 X
  76.                 string descUser = string.Empty;//目的用户  a4 Q6 {& Q0 R" O( x
  77.                 while (true)
    # {7 C- Z4 i. S7 w2 D- V
  78.                 {
    6 B: I" |, e+ w8 C
  79.                     if (socket.State == WebSocketState.Open)
    0 V. j) G6 G: U2 H+ z
  80.                     {
    1 Z: Z0 s8 {" d; l  t
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);" w) e6 A5 N- @8 {: y; Y
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    ) w) ]% _% R; D$ s5 x. b3 `- S  ~  b6 ]

  83. ! F' A9 u# x% c! a; b3 `4 n1 u
  84.                         #region 消息处理(字符截取、消息转发)
    ; N9 `$ j8 t7 m1 t  g# i. X
  85.                         try
    , g" m& |: F8 T  \- C5 u  g" e
  86.                         {
    - F1 V! y& Q/ j* H* F# K
  87.                             #region 关闭Socket处理,删除连接池
    0 O0 ?" z3 u6 Y* x3 K, \9 ^
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    ) s# ]' e' o  t% Q
  89.                             {
    1 N9 E' n/ H7 U1 j
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    9 @7 x' n/ z& a6 m: ~1 {
  91.                                 break;
    ' m  m5 v1 x) Y! _
  92.                             }8 F$ h2 @3 p' Z0 X" d
  93.                             #endregion7 d: R% ]3 [4 x4 a

  94. 2 X) D0 p, ~! U: b, e: y# [: w
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    . r" P% v9 q5 f5 Q  Y' J$ h
  96.                             string[] msgList = userMsg.Split('|');
    ( c" X" D& P* k  R3 y2 D9 |: f1 H
  97.                             if (msgList.Length == 2)" o7 [, P, S: X+ y
  98.                             {
    , V# ?0 w' c; _2 u9 t( a  {4 r4 a6 M5 s
  99.                                 if (msgList[0].Trim().Length > 0)
    4 J" C. G/ V# H  f
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户0 k2 \- j  `& Z% j& K) _
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));" L& m9 m: g( n# p" e
  102.                             }" z+ s3 O4 Z/ _" [! ~1 V
  103.                             else
    1 t+ j$ {. B/ H( _6 I/ ?
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));  k2 m0 [# \( S  J# I4 r# n. l
  105. ' p, H& {- [9 M1 A, R$ l9 V: V7 {
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
      S3 I' m5 R" P+ G; a
  107.                             {1 d* c5 x& F; b7 V
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    8 c/ g, Q& m- M5 o& @8 [; r
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)4 ]" Y0 u' _, k/ g# J# E
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);# T0 ]5 W. w- l" z+ K
  111.                             }9 z+ j: _$ K/ D% X
  112.                             else$ g2 x) ?+ E! R: w9 b# U
  113.                             {
    " e9 T2 X6 t4 L+ {- N
  114.                                 Task.Run(() =>
    ( W! q/ [1 G+ z) P% X0 Y
  115.                                 {
    ' R) o8 p+ V. ]* r: S7 e# y- Z0 `
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中9 H7 }8 [6 L$ @# \0 |& V
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());2 I3 b2 ~$ @9 F; M0 M& c
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息+ o+ b% t3 i5 E, Q
  119.                                 });8 K/ {1 \: z. t% c8 `
  120.                             }! n# Q5 D8 D( {# H. s  j9 L
  121.                         }
    4 e* M! Q9 D& `5 @
  122.                         catch (Exception exs)
    2 o% s6 L6 v9 W
  123.                         {- h4 p7 N0 j3 D# J; @: n
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
      {( q2 J7 B/ A. t6 ^
  125.                         }/ y9 n, d  W4 @; e0 U
  126.                         #endregion
    ( B2 r3 O2 u+ I% r) G7 w1 H* I& N
  127.                     }
    * `+ n# ?- z. J0 \) k9 i0 C% c
  128.                     else2 U  A% |, M, D
  129.                     {
      W5 J3 {- r( X# l+ z  p5 f
  130.                         break;
    2 B5 w( _$ ?& j' `% T
  131.                     }0 b4 Q( l' U% Q$ q) t
  132.                 }//while end' h, I! k' w9 B8 x% P( c5 O
  133.             }3 I% S+ y, a% x0 n
  134.             catch (Exception ex)' l! i4 c3 n9 n8 }) Z9 o3 t
  135.             {
    . H- Z0 V4 G. [
  136.                 //整体异常处理
    " t) ~/ ^+ H+ i& h. n
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);4 b/ P7 [1 m, K
  138.             }
    & H8 ]& f8 e: ~8 \
  139.         }! |4 F, C. i8 p) z# W
  140. 4 g$ j9 t! q* v# S9 }" G  p
  141. ! J# M2 S9 F# W) G- S% d
  142.         public bool IsReusable
    3 D2 k4 M: u2 H. U# F  |2 n
  143.         {" q  i9 i* y4 {+ G
  144.             get: V% X# n- u6 G) @
  145.             {
    3 r0 S: k! h: s3 _
  146.                 return false;
    & w- x$ t% l' T# w5 ^* w* w1 H/ M
  147.             }
    " i, }! a0 o7 d4 K6 I
  148.         }5 W5 q% T/ @5 s' [; r9 a- ?5 r0 \
  149.     }9 w  i6 p) G% `5 i& A& L
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

% f: s  p3 x/ I" v
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-12 22:49 , Processed in 0.131861 second(s), 22 queries .

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