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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
6 R4 g  L1 b, r" ?" ]7 F. }
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    3 `  K; I5 J* G, s$ R
  2. using System.Collections.Generic;
    * e3 H0 X* }- E- q6 D3 V% n. m
  3. using System.Linq;0 y. x3 U6 H" W& Q
  4. using System.Net.WebSockets;9 D9 I2 v+ b0 c; F# e
  5. using System.Text;
    9 d$ l1 e' b# W4 r% p7 v% y+ b) a
  6. using System.Threading;6 j8 V- ~, U9 N5 o
  7. using System.Threading.Tasks;1 a* ?, [. ]% I
  8. using System.Web;
    % n6 s0 V* |3 u' |
  9. using System.Web.WebSockets;
    . V0 {! ^7 G% o# |5 v2 G7 ?

  10. & c" S8 [" ^. d( E( k3 _
  11. 5 z! n$ {0 E! w! [/ X1 W
  12. namespace WebApplicationWebsocketHandler6 k9 S$ ~: E: [" }" _5 a8 F" ~/ m
  13. {
    5 Q. f2 n7 h; I) t
  14.     /// <summary>
    ( O, t# C. T4 l6 _1 ?) p" K
  15.     /// 离线消息6 n7 h8 Z9 S" B; ?6 _8 j
  16.     /// </summary>! S, j* y: g- c
  17.     public class MessageInfo
    & n8 W7 o5 e4 {4 u
  18.     {
    7 J8 \' V3 U, Q( n5 ?2 i4 e2 J- E+ g
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    # q' v7 {. E9 R# s
  20.         {8 N' H7 i- L. i: E$ R
  21.             MsgTime = _MsgTime;
    & U0 w' H* D2 [$ U8 N! O
  22.             MsgContent = _MsgContent;
    ' B. L- T5 I9 i3 V# }" x, ?% ~4 A) b
  23.         }
    8 F* {  [( p  [/ P& i) T
  24.         public DateTime MsgTime { get; set; }
      l# y3 h, J# M2 r; a0 \) Y
  25.         public ArraySegment<byte> MsgContent { get; set; }
    * {- q/ N! a, z# Y- u1 G* y
  26.     }
    9 \+ ~' F/ I. l& O7 y4 [9 l5 t

  27. 9 |+ H, d& d% k; z8 d/ y$ e  ~
  28. 9 e5 S9 [3 b1 R: g. I
  29. 3 U  h. S+ m" t0 L
  30. 5 R; E$ {& s4 C" [9 Y
  31.     /// <summary>( {* ^, q0 T. u4 l) v  q$ a
  32.     /// Handler1 的摘要说明) s7 h! H  Y  E. D1 V/ M
  33.     /// </summary>
    ! S  U2 q1 q/ Y. n0 L1 {
  34.     public class Handler1 : IHttpHandler! }* M) c4 C; s
  35.     {6 C8 `$ f$ c: H- U
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池( P6 a5 m# V7 F+ \
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    7 i, Q1 o% x0 r3 X
  38.         public void ProcessRequest(HttpContext context)
    ; h- ^! b; d5 j4 ?
  39.         {
      p2 h( L- h- v
  40.             //context.Response.ContentType = "text/plain";
    6 B  l2 v1 s: f8 f
  41.             //context.Response.Write("Hello World");/ i/ X& K; a/ ~2 Y& V, }
  42.             if (context.IsWebSocketRequest)
    $ w: _  z: r4 ^- X) O
  43.             {
    0 x6 y9 e* O4 E0 i9 t
  44.                 context.AcceptWebSocketRequest(ProcessChat);1 c$ \9 |4 j( o& I
  45.             }
    & D1 J9 b3 o" R
  46.         }
    ( ]& ~0 N6 U2 \+ R' {' E

  47. + x9 F- p  S* p+ G5 q$ ?
  48.         private async Task ProcessChat(AspNetWebSocketContext context)% a& P! M, ], ~6 y
  49.         {. o2 \, E, F" Y0 Q# q8 T
  50.             WebSocket socket = context.WebSocket;6 F2 R, ~  @. ]" k* R  b
  51.             string user = context.QueryString["user"].ToString();# D  u' C/ \! m# r3 D9 @1 t
  52. ; q: a% |1 k# Y8 j" d, b
  53.             try
    7 ?; I$ p9 l0 A; n+ Z
  54.             {
    % |5 K  X8 I" ]) Z+ Z
  55.                 #region 用户添加连接池
    ' v6 U: N7 K; A% T4 e
  56.                 //第一次open时,添加到连接池中
    % d4 T3 h5 R: l6 s
  57.                 if (!CONNECT_POOL.ContainsKey(user))( L8 ^$ y) X- F' g) [
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    * U1 Q/ n# |, p4 p/ o" C
  59.                 else
    " i- J2 k& \/ b  @- m
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新! X% \3 i- e' S7 k
  61.                         CONNECT_POOL[user] = socket;8 E) n, i6 X7 ]9 a! N, l* n: T
  62.                 #endregion
    : @9 M0 q, y& l, T# v

  63. " |/ E+ P6 X9 D& H& F& R
  64.                 #region 离线消息处理
    ) [1 d* s' r4 d% {2 u0 Y
  65.                 if (MESSAGE_POOL.ContainsKey(user))/ Y, i& t& f. ~1 j) {
  66.                 {' h) v% p4 H; R
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];5 P" {; N% G. o- R
  68.                     foreach (MessageInfo item in msgs)' n; L# K1 ^$ k3 C% F2 }) s
  69.                     {# M1 ^  I, M: @& T: C/ n
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    0 |+ V8 A) N0 I9 d: r0 Q' k
  71.                     }
    6 H9 M& o- j& O3 k
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息$ U: q- K" C! j9 ?* K
  73.                 }
    2 ^* Z/ a5 J1 ]" C
  74.                 #endregion
    6 K" g" L) y! v; A+ J" m0 D

  75. ! b9 z7 @. d( C; b' t
  76.                 string descUser = string.Empty;//目的用户0 G. `1 |0 [3 b7 J/ B. G
  77.                 while (true)
    * v( m& B- p) O1 j
  78.                 {
    3 ~- M8 T, j8 ^( _0 }# [0 n
  79.                     if (socket.State == WebSocketState.Open)' R8 N4 H" e9 {+ Y, D. b' g
  80.                     {8 N% N6 w, Q9 O. ~1 ?1 P
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);2 p, [( f4 s5 P( |6 @0 s/ \
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);: e3 L) V3 u' o8 o

  83. ! @% N5 U" p  l( S2 z$ A
  84.                         #region 消息处理(字符截取、消息转发)
    ! o1 T8 D. d; c' ~
  85.                         try& b! Z, G  J: h8 h6 n
  86.                         {
    / D2 ~! \4 F) [( v% o% [  H
  87.                             #region 关闭Socket处理,删除连接池& A; ^6 U+ S5 ^# k
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    : y% [' r6 x& a- F, _
  89.                             {$ |; r' L, ]# W; V
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池1 O$ j: {* u9 l# E
  91.                                 break;( S% Z, n' u  G, }. N
  92.                             }( d% }5 R+ p3 E8 t* L
  93.                             #endregion- L+ M% v3 r3 b$ s5 N: B

  94. 0 I4 ~' c7 w% H$ l- _0 V* J8 f
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息  e( p' L" ^* n1 b  I1 e! \2 m9 s
  96.                             string[] msgList = userMsg.Split('|');
    0 i2 m4 u7 o' g, X
  97.                             if (msgList.Length == 2)0 E) I1 ?8 p* L* ^/ l
  98.                             {  ?2 x2 X, E7 g2 E  X# ^
  99.                                 if (msgList[0].Trim().Length > 0)
    # y* M# U8 ?3 T* s  f+ _2 H
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    , [' x( L/ p: `9 O
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));0 _- c' y1 a" {9 g+ ?, Q
  102.                             }+ n, O$ l& T# p9 R4 t1 b
  103.                             else* e& x- F& N  E( R' H: q: |
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));  @/ v$ `8 A: g( G! w" o

  105. 7 s1 c/ ^, {; x% G$ w
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线; ]- v  o: ^% o& k/ l7 S  E
  107.                             {
    & |9 T3 t$ p+ q! [, ?0 W
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端: K9 P* J' f) Y* g" S
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    # s+ V3 ^- U2 }, H2 o: t4 I
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    ! {4 B. p! I/ E
  111.                             }# R- V3 o! Y' P3 O8 g, V7 j
  112.                             else
    - ]; _& \% p  e+ Z/ k# s
  113.                             {, e! N9 d# p  E
  114.                                 Task.Run(() =>
    5 G4 p" w/ l  T; |1 W9 I2 d
  115.                                 {
    $ Z, U* `7 X9 I4 G' \3 y- x% T
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中& @4 h$ g  }2 i2 `, a
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    3 o+ q  x3 m4 g; h2 E+ K# h
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    ! F4 b' H. _5 K, `$ N' |' p
  119.                                 });
    7 \- q8 }' o# y& O2 s5 G* I
  120.                             }, R( T0 n4 I  T$ l* s, B6 c
  121.                         }
    5 s! x1 K4 M/ l1 V; i
  122.                         catch (Exception exs)
    & X' W! ]9 |& f; q
  123.                         {
    ! M3 _# K3 ?  Q& R0 t0 \- {
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    - l$ U2 B6 k3 c! y
  125.                         }$ Q; ~+ @7 y5 W) Y" f4 ^' K8 K
  126.                         #endregion
    - M' n) m) i% B5 ~+ d) e
  127.                     }6 h0 q0 M0 v1 v& p; ^- Y
  128.                     else/ \# a  y0 ]/ q
  129.                     {
    # ~" _4 z+ s* K
  130.                         break;: @  i0 X7 e/ |& k5 K2 p) q' ?( N
  131.                     }: [  o7 l; `) U& \5 D
  132.                 }//while end$ ^8 f) U4 b6 E, [4 e( V4 S
  133.             }
    7 h3 Z$ _6 D8 U2 ]
  134.             catch (Exception ex)
    4 A& `8 ^0 [, i, S; f6 M. `
  135.             {
    ( \$ }+ D  q" X' U/ E; k/ S! d4 }
  136.                 //整体异常处理
    ' k+ d4 Q& ?& R+ Y0 [
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    3 _; _* G+ r$ J4 n: S) F
  138.             }! L' x. v: i1 q6 w3 j
  139.         }9 F1 v1 e( q: ^

  140. 2 Z: V2 B1 f/ N% A3 P- N8 f
  141. $ P" _. A6 d3 Y0 w
  142.         public bool IsReusable
    5 p- r9 \1 l: O) I2 R
  143.         {
    ' Y: M$ [( `; R; t9 U& X! l
  144.             get
    , V% }; L; t" y  R1 ~2 P) O2 {
  145.             {/ U! {+ K7 r$ H4 t2 x: e$ D
  146.                 return false;
    7 }8 I6 Z3 `; E6 Z7 F! k* X
  147.             }
    5 l0 c4 @% Z. A$ ]5 T/ d) V2 V
  148.         }: S* G& [4 P3 O
  149.     }
    5 z; m: Y5 c* r5 Z' v! h8 X
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
9 S! _; M/ b! t% |9 Y6 F
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-9-21 02:07 , Processed in 0.061296 second(s), 22 queries .

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