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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |正序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
- w8 d( ^1 y5 Q- ^) X5 \0 A
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    2 n4 ~- j5 N! {1 n1 N8 |
  2. using System.Collections.Generic;
    ' e: F, P; x8 y0 Y( L- s9 M
  3. using System.Linq;& c" D1 Y  Q! B  ?: M
  4. using System.Net.WebSockets;# r+ e6 L2 Z- L8 F
  5. using System.Text;
    . |9 \. w2 [0 P+ g
  6. using System.Threading;' s" y- Y6 c. \
  7. using System.Threading.Tasks;3 z7 j6 W8 Q& W7 X. ~" V' Z
  8. using System.Web;9 |5 u! t  I4 o+ V0 D4 k( r' {6 e
  9. using System.Web.WebSockets;
    8 y2 P, d- U8 q

  10. 9 B) O' _$ e; O& W0 G

  11. & b$ ]* {, p  B; z
  12. namespace WebApplicationWebsocketHandler
    ' B5 T+ ]# q+ C- t1 l
  13. {
    8 g2 E; h* O, t: {3 F. _0 N0 Q
  14.     /// <summary>- p. W# K0 V" _7 W, s# }
  15.     /// 离线消息
    * I, D* C% @0 p& R: |  c% J
  16.     /// </summary>) M) c. c% a+ N3 M/ O! u) Y- L
  17.     public class MessageInfo; K: x- Q* h# h; V
  18.     {
    , w/ E! f- k' W3 a/ Z; H
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)7 ~, Z( }0 s, e! L
  20.         {
    ) p- u) y' o: f' D" F* I
  21.             MsgTime = _MsgTime;
    * }2 R! M6 ?8 ]3 ~5 s* w( h, m
  22.             MsgContent = _MsgContent;( ]: Y- t0 @3 d! c* K
  23.         }6 W: K# ^# I/ r" b2 a; f4 O
  24.         public DateTime MsgTime { get; set; }
    4 I1 F( O1 m& k" j3 k
  25.         public ArraySegment<byte> MsgContent { get; set; }2 s  N5 r) v# O/ E4 ]# a
  26.     }# R7 y- D: G' @" \7 B' }

  27. " Q' h3 n" F- V
  28. " `# B# N- T( @7 _' y) b

  29. 3 o1 \; r! e; A+ _

  30. 5 c! X( Q4 V* N* j& n
  31.     /// <summary>" K; M! i- w- }) U( u1 w. u6 Z
  32.     /// Handler1 的摘要说明2 H7 N  b- J- @
  33.     /// </summary># n3 b2 v+ e$ K. ?, D0 w! @
  34.     public class Handler1 : IHttpHandler8 D5 _6 N, U! d: s  ]; f" G4 {
  35.     {
    7 Z4 `1 ^' u) n  ]
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池3 [5 z( l# q7 f0 `2 X; Z+ B
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池+ `' C' m8 L. x% J1 Y
  38.         public void ProcessRequest(HttpContext context)
    4 X: h; \! d' x5 g& l3 j- m* [
  39.         {
    ( |. O8 _6 p! O0 ?0 a
  40.             //context.Response.ContentType = "text/plain";
    ( f: ?, P4 z3 W- H/ t9 Z& x( q9 x
  41.             //context.Response.Write("Hello World");
    ; ^  y" k+ u$ O' W$ U
  42.             if (context.IsWebSocketRequest)) I6 {; U; c  H4 p: c* ~, x- q
  43.             {
    2 ?; W. L4 G. y7 \
  44.                 context.AcceptWebSocketRequest(ProcessChat);$ M8 P/ e0 v! I" R
  45.             }
    8 b$ {. h) K) o/ f5 I' |6 S; v
  46.         }
    / I7 L% H6 l1 J( e7 G
  47. ; D! J3 t0 Y8 q6 z- E! J
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    + ?0 A/ Y* t! z
  49.         {9 q) p0 X8 m0 Q7 c% c7 ^0 D9 p. o, R
  50.             WebSocket socket = context.WebSocket;: l1 |7 @' C+ F: W9 q
  51.             string user = context.QueryString["user"].ToString();
    * [+ q9 q; S3 @. \

  52. ) @$ H' h/ J3 b* R5 G
  53.             try( d, m- W7 u1 p* K$ [
  54.             {# U6 s% s& C# W2 H; E1 Q4 W3 {
  55.                 #region 用户添加连接池) V0 H: g. m5 J$ [/ ]6 T
  56.                 //第一次open时,添加到连接池中" N$ {3 p8 G$ \( V" O" n
  57.                 if (!CONNECT_POOL.ContainsKey(user))/ c( I: o* d& H+ e  U
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加  D+ i1 g& y) Q" Z3 F  D
  59.                 else
    1 I) f/ x0 [: {% I/ i' d* S& o8 R1 ?
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新/ D3 N, W$ g4 t; E5 s- ]2 B
  61.                         CONNECT_POOL[user] = socket;
    6 F' w9 b) C6 D0 o
  62.                 #endregion% H( w% ?/ d# E( y1 {6 [7 g6 \
  63. 5 E3 R3 j% P  Z" Q% X4 W( V! N% i
  64.                 #region 离线消息处理
    / i3 V: `# y" E" W2 B- Y+ P
  65.                 if (MESSAGE_POOL.ContainsKey(user))5 r1 |: i1 s$ p8 [/ c
  66.                 {1 q/ s) D6 t3 n" h$ W" a+ y( [
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    ! H/ j0 k4 Q* ~1 X# z. j: G
  68.                     foreach (MessageInfo item in msgs)
    , p; J6 N0 H3 y* {: Z) @
  69.                     {
    ! V# P/ x/ R, v2 Y  i7 p0 v
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    5 y% \5 _6 a; @/ @  Y
  71.                     }& P) x2 k; U9 U: E$ q5 a, q3 Q1 U
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    2 a, Y% F( S  {+ \* }
  73.                 }' r& p" `7 e9 ]5 x* y
  74.                 #endregion
      {  S2 v; W- K) L1 p( R
  75. % i* \; J# _( X% b
  76.                 string descUser = string.Empty;//目的用户
    9 ^. Z1 ]1 @5 C
  77.                 while (true)
    . _8 y$ o# e6 v- `
  78.                 {
    , d3 T4 o; ^2 ?# O% a0 W( F
  79.                     if (socket.State == WebSocketState.Open)
    ( e. ^. v' |; v/ i5 u+ U3 x
  80.                     {+ r' }( U. ]; o2 H! A
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);$ v* O8 K, u8 G6 |
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);. ^- Y- Z  U$ N9 ^
  83. 0 N. x: D& W+ g
  84.                         #region 消息处理(字符截取、消息转发)1 K6 ]  |, i( X! H4 {
  85.                         try
    3 D! W: D! k2 ], y# S& `
  86.                         {  _; p) g; s2 q/ n- l7 }; h6 ?
  87.                             #region 关闭Socket处理,删除连接池8 N# y3 F8 {$ k& P
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
      r1 e! z6 _- R; n6 B# X0 G  X
  89.                             {
    / r1 b% B) b1 B* x& k
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    $ m2 }& U# o& v" P6 c. j
  91.                                 break;/ L! M( y5 a; K$ u" i
  92.                             }
    ) x# Y. ^" }2 H
  93.                             #endregion
    ! {# z" P4 N3 Y0 T7 P( p3 }% T# I

  94. 4 o. d  [( ^# H( z
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    , o. }" x+ B* a* ]- c
  96.                             string[] msgList = userMsg.Split('|');7 R7 V1 g. S) C! c
  97.                             if (msgList.Length == 2); v  M# t$ U% K8 t9 S" H
  98.                             {5 R# \( d3 f3 o0 G  n
  99.                                 if (msgList[0].Trim().Length > 0)
    ) W$ `" X. s. B7 \* V4 }8 n- M
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    8 C2 r, \3 [  }' u$ p& v. r
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    4 M# u) M3 k) t3 E8 A" j0 s3 h
  102.                             }
    : Z3 V7 u* e0 g5 V3 r
  103.                             else7 j+ Q* P) b4 U& X4 D* N0 m6 |; A* l
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));0 F+ M  Z) a5 {' j& ]+ s1 f3 i7 O
  105. ( w1 T( N5 o' j% e, `" l
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线. H9 B- @" ^6 p$ S% W
  107.                             {
    5 [9 Y7 n) v7 B- `8 z5 e& f
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端1 y- _6 C5 |" i+ ?; n! `3 W7 }
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)9 @0 ~; k( @  y  N5 d. u& P4 t
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    ! E/ F; ^9 V8 T& {) U/ @/ {
  111.                             }1 m6 p: q" s8 b; k: C1 p- P* Z/ ^
  112.                             else! T% J8 m# A* R' r& }" N# h2 z
  113.                             {
    / H" r2 I1 M; D/ O/ W8 q6 Q
  114.                                 Task.Run(() =>
    / u3 {' U. H$ h  Y: g0 @0 v. V# P
  115.                                 {+ J) r6 d+ r, @% y
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中$ F# b8 Q. {4 p% Y% O
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());5 u- n1 n: O% i/ G/ W1 H! d: \
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息  e! y& {" `: b+ ^8 w
  119.                                 });% P: U! Z, {3 p* E+ P) n! X
  120.                             }
    ( A0 f  v0 x8 H2 \
  121.                         }
    / E5 L0 l! f. d# |- J) T1 S0 ~* q
  122.                         catch (Exception exs)
    $ y& g* m" B' U# |  t+ m
  123.                         {
    0 |2 J( x$ A6 Z: a
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息: ^$ |0 [+ T% O; L+ ?  `
  125.                         }
    / y! @& U6 C2 k  ]) o
  126.                         #endregion2 y7 B0 M! u6 J# s1 P' D! {
  127.                     }0 m  X* J5 j/ V& I1 W
  128.                     else2 c# N# C- a. ^6 t+ x- P
  129.                     {2 R6 @: ?- n  g
  130.                         break;' ]$ |3 w/ C' a% n
  131.                     }. n1 C6 @5 C: M! Q1 m. u1 f
  132.                 }//while end
    0 [& X/ {# A& \( R
  133.             }; h5 h! l1 w4 ^+ f+ j, Y0 ?/ f
  134.             catch (Exception ex)8 Z! K  j3 n6 E) l
  135.             {
    9 f9 K! h$ s9 F
  136.                 //整体异常处理
    8 i6 @/ Z( ~% D% d2 x) G5 ?* \
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    % r2 z$ ~" L; n* _: k, _) ^
  138.             }
    ! E) z9 C' L6 R; G  j
  139.         }
    4 R# W! c9 \+ T  J4 d* k

  140.   @3 H% W! Q6 b* J0 A5 M

  141. ( I! P1 }1 Y! K
  142.         public bool IsReusable
    ) M- H. ~4 V% y
  143.         {* ]% ?  |+ I$ R! G" n! S; |$ O$ n, ~
  144.             get
    + x+ t2 y, |/ x$ z6 m" X3 A1 |0 a
  145.             {
    ' d2 k# z6 x) I
  146.                 return false;, [4 m- q9 m1 W; T2 a4 U4 g
  147.             }' V- r2 ]. F/ a, u
  148.         }2 ^! ^& k2 H5 |6 e
  149.     }
    % ~8 x) W$ z3 n2 Z
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
: d9 G  Y: X+ Y; D; k. h; o
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-20 00:14 , Processed in 0.130206 second(s), 23 queries .

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