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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目

4 T( g  d3 `4 s& p. o" a8 P* ]
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;& [& l1 E' @1 y& _
  2. using System.Collections.Generic;6 I& x' u, f$ K# B) W
  3. using System.Linq;: l- T/ L8 b8 a( V8 W
  4. using System.Net.WebSockets;( v% Y6 B  ^  g! V7 L  A! f" l2 n
  5. using System.Text;
    : D( M- s* A1 D) h6 t3 }; v7 W
  6. using System.Threading;" D% K5 u% U9 R
  7. using System.Threading.Tasks;
    : F) [+ \0 e# R
  8. using System.Web;
    & l1 D1 F2 M( E4 F# f( B4 H
  9. using System.Web.WebSockets;8 e: K1 Z( S* N5 M8 p0 i8 ?; T
  10. 3 ^; {- M* |; x% f5 |

  11. ) i8 V& U: a& {- V) x" b6 b0 o+ a
  12. namespace WebApplicationWebsocketHandler' e0 }" _* [: N
  13. {1 ]0 a4 ?* s1 i  A
  14.     /// <summary>1 ^' F( b7 p" X6 L3 T; k
  15.     /// 离线消息
    2 Q5 q6 l! ^5 ]' u$ \/ V. D4 y  Y
  16.     /// </summary>% w  t0 n6 {9 V8 E6 {: L
  17.     public class MessageInfo, \5 N. H, }$ H& `8 f" q) ~
  18.     {9 R  u5 X( K9 q7 L
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)( m1 a* V" ?8 z2 |% [$ K
  20.         {
    0 {# N/ d1 y$ c% C' I6 O: H
  21.             MsgTime = _MsgTime;
    : r7 E1 ~* L! t- S
  22.             MsgContent = _MsgContent;5 t- I+ z4 t- b% t1 ]* b9 m
  23.         }' `7 y% }4 l$ s: u
  24.         public DateTime MsgTime { get; set; }
    & Y! R7 b3 ?( H. p" [  b9 q
  25.         public ArraySegment<byte> MsgContent { get; set; }; J  p/ }; L/ h: N5 z! s* U- x2 \
  26.     }' D9 W4 q& p$ v5 o
  27. 1 K* @! L( Q7 C( i2 _$ H

  28. + a8 g7 G3 r2 i: S% O$ H
  29. ' s- d  W+ _' \2 ^

  30.   N: j1 K0 o# B
  31.     /// <summary>
    : Z) e! v- u8 Z3 v
  32.     /// Handler1 的摘要说明
    2 U/ y' a" z" X! s+ e+ M8 p' I
  33.     /// </summary>1 f- N# I+ i/ \" D7 ]5 f
  34.     public class Handler1 : IHttpHandler
    6 l; L6 K" \  E+ Y3 q5 v
  35.     {/ K$ [7 S5 g$ q3 E7 p6 g+ u. X
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    / K" W: S- d. y% d" i" o1 ]) h
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池. v7 U. ?8 u4 p
  38.         public void ProcessRequest(HttpContext context)
    $ f3 N% W4 x/ M1 \/ S) K! s
  39.         {
    / n1 h' h* j5 A
  40.             //context.Response.ContentType = "text/plain";
    6 ~  w$ {2 E  o" f) I
  41.             //context.Response.Write("Hello World");; I5 s/ q, t6 Z+ {: @
  42.             if (context.IsWebSocketRequest)- f# _+ j/ ^. x: e2 o
  43.             {  k( H9 t# q( M) X- J! i
  44.                 context.AcceptWebSocketRequest(ProcessChat);6 x' C- O! N- |& j1 X' V- n1 q* B6 {
  45.             }
    . L0 z& i( h3 |8 \
  46.         }
    . h0 D5 C* ?# g" V

  47. 9 f; h! D; u  k7 e+ _! K. [- P
  48.         private async Task ProcessChat(AspNetWebSocketContext context)3 J8 l3 t3 P, B8 e3 r
  49.         {
    * t3 t* H) F% F  l
  50.             WebSocket socket = context.WebSocket;
    ; q8 [, J- O7 A8 \5 b
  51.             string user = context.QueryString["user"].ToString();: S" S: U, N) g# `2 ^/ z) b
  52. % C6 m8 C  H- }: y- s
  53.             try$ n( u: B: O, O1 k+ v& i$ T
  54.             {4 L+ e) ]& V  W
  55.                 #region 用户添加连接池1 \( i9 U6 U6 T6 H& P0 t: U/ q# J
  56.                 //第一次open时,添加到连接池中6 a: `2 R7 W* R/ G6 h+ p6 `
  57.                 if (!CONNECT_POOL.ContainsKey(user))
      @- m* Y6 E1 a/ x7 Z
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加1 y$ A' {; ^$ l( \
  59.                 else
    ) G$ S1 u4 Z4 d% k$ v7 N' a
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    + {5 V% ?% `( V! i
  61.                         CONNECT_POOL[user] = socket;
    # r* T9 C( C1 R% X# n% f
  62.                 #endregion2 l. G+ q( H, k9 C3 Q7 m5 D9 P
  63. - @7 `/ |: e( K$ m+ _" T
  64.                 #region 离线消息处理. g6 ]+ l2 J, G1 R% L
  65.                 if (MESSAGE_POOL.ContainsKey(user))7 p9 v! t# U0 L8 K" }- x; B
  66.                 {
    5 t# w6 a1 H5 i7 v; ~: g
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
      j! ?  F: w; W. _
  68.                     foreach (MessageInfo item in msgs)
    ! m; P4 D+ w- ~, l
  69.                     {0 ]* u) v- e5 v4 R) \
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    ( N% [, P; y1 m
  71.                     }
    ' l; X- S/ A6 L: s4 ?, [! q+ {) V
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息- _" o# Z$ @: q) w: n
  73.                 }9 P$ c0 A: w* x( X; n! Q* w# e
  74.                 #endregion, q$ O# k- F; ^4 X( E  R; b0 {

  75. 1 m( p2 \7 \0 F4 K7 K
  76.                 string descUser = string.Empty;//目的用户, d/ b# U3 O5 q0 J) P: J
  77.                 while (true)
    , Z3 V6 [' @! i$ z, c
  78.                 {
    6 Z, L6 z* }# r
  79.                     if (socket.State == WebSocketState.Open)3 b9 u2 D2 c; o+ o
  80.                     {, j$ c0 J4 {4 v8 l( I) C2 W
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    , l! g: s: {* H; `8 P
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    0 y6 b7 Z* O4 K8 R# U& P$ M4 X
  83. ; b+ Q4 }2 w0 K* i
  84.                         #region 消息处理(字符截取、消息转发)
    ; d+ m1 b8 O( D; \! T7 `
  85.                         try7 a1 N9 Q8 H9 I) n! n7 w- C; K
  86.                         {: t5 @9 J9 H: R- Z$ [# p
  87.                             #region 关闭Socket处理,删除连接池
    5 H/ t5 U$ {4 u+ p8 b- Z
  88.                             if (socket.State != WebSocketState.Open)//连接关闭  }- |6 \  s: ^9 U5 k; ?  c
  89.                             {
    7 O$ A& K; @  S/ Z3 L  g
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    3 [6 y3 J) J% P3 O
  91.                                 break;
    8 x% j- M% b9 j  U
  92.                             }
    * \- F  W" q" ]2 ?: s) Q
  93.                             #endregion
    ( A/ n0 {* |1 q4 y

  94. ' N/ O7 M# i5 _& L6 J
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息( I) Z( w* y: n& d( \' q: c
  96.                             string[] msgList = userMsg.Split('|');7 P, z7 s8 Q+ S4 M* M
  97.                             if (msgList.Length == 2)
    & B; \; w, H! p, B. j# G
  98.                             {
    9 q! N6 O. l2 I* d
  99.                                 if (msgList[0].Trim().Length > 0)' l9 H$ o. l; A9 g0 V( L
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户% m0 Q( `0 G) I: z( \! M
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));# K5 ?0 E8 X# g+ S; a6 w- |
  102.                             }% U- b! y+ I# n' R6 I4 y
  103.                             else3 v  T8 T0 a+ H. t7 ^
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    ! M( s, H: U1 W; c/ \
  105. 4 w8 |  N3 }/ R' i% v+ C1 z, h
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线7 f; g+ A8 T5 ^5 x
  107.                             {
    ; Y  T2 l' Y% y% \/ i0 N
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    ' ?0 u9 U8 ~- M0 r7 s* r8 H- _
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)- {3 }' p$ X6 f
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    " P& y* a) M3 }( M
  111.                             }
    - G2 K& V6 Q8 c- _/ p
  112.                             else( G  a- m( L) C
  113.                             {
    & y; {- @3 v* W  O
  114.                                 Task.Run(() =>5 u$ E8 `9 P0 X- C
  115.                                 {0 a8 a. L4 t0 p4 U5 M$ j, r( a
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    ( L1 G/ i" U( }
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());9 D+ |  Q" U% |6 R% I" {
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    7 P3 A2 {, c" Q6 t( p+ Y+ L; R  x
  119.                                 });
    % x  t, w5 ^! b  I! @% t
  120.                             }8 p, `$ g4 k4 ~
  121.                         }
    5 m/ e+ u: A9 x! G  F3 I
  122.                         catch (Exception exs)8 a# O  Y' O6 J6 F4 r
  123.                         {1 D( Y6 `4 H" u& G! _
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
      A  m; J: ^3 ~7 A3 ?
  125.                         }
    . q! ?. P, p1 f  n3 V" h
  126.                         #endregion8 d# W& r* X" t: z
  127.                     }- [2 K! u0 T9 ?& h  F' x' L' {
  128.                     else: [) n' f) R& |' _
  129.                     {7 l4 q1 @0 e. E  z  A/ T
  130.                         break;& ]- y8 Z% o2 d/ K4 [8 G1 r
  131.                     }
    0 _; W' c* H1 ~( e+ G
  132.                 }//while end7 b  {7 @0 H3 e* L0 g* U  n, \
  133.             }  G3 Z5 n' P9 R
  134.             catch (Exception ex): j, L' X) r1 h& [
  135.             {2 f  w6 ~: s$ C. J/ h+ {
  136.                 //整体异常处理
    ) q/ y1 E7 Q, b2 n% X
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    # }3 k) N; j6 u. A
  138.             }
    . \, s/ K" g  S% P9 T
  139.         }
    . C  i% m: N# j" z+ n. v
  140. ' g% I$ Q8 |! l$ J% N! U# t( L

  141. ) C+ Z  m  a0 Z7 ^/ m) Y7 _& X+ j- v
  142.         public bool IsReusable
    0 Z, H% L) W- s0 M$ r& G1 r8 q7 q' Z
  143.         {
    ) t$ b6 h0 ^- z6 y7 R1 \
  144.             get3 {2 x+ W) a3 O% Q+ P9 [* \+ g* m
  145.             {
    ! Z3 F0 k$ m& ~$ }  O6 f  @/ ]
  146.                 return false;. C4 t! Q) W* O9 Z1 P: [
  147.             }% P( q; p8 \* w$ F- e. A
  148.         }
    : G7 q% X1 O3 R% D+ C
  149.     }
    % Z7 A- o' N7 z; F1 z
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
: h8 w) S, U7 p+ d6 u
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-3-16 21:08 , Processed in 0.091681 second(s), 22 queries .

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