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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
! y' A6 C0 B/ A2 k4 @
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;# ^% o5 b! Y( [8 _( g7 I- @$ S
  2. using System.Collections.Generic;. N' Z  w' b8 U# p1 \* W+ K) z0 I
  3. using System.Linq;4 H0 Q+ q+ x$ z1 f2 W
  4. using System.Net.WebSockets;; M% B0 A: b/ x  \1 j/ A) C  F
  5. using System.Text;% s6 Y- e) n& L
  6. using System.Threading;
    0 e* t/ Z6 B- L. v. H
  7. using System.Threading.Tasks;
    3 [2 e# I6 R( O. e$ w
  8. using System.Web;$ f0 h( t' m" ^; n1 N! f  k
  9. using System.Web.WebSockets;) D1 y5 M3 ~" f" w$ X+ e, P. B7 {

  10. ) M; l- t. M& B, j

  11. & G1 |8 ?% Q1 T, |
  12. namespace WebApplicationWebsocketHandler, x. V8 j) S! K4 V" d* y
  13. {
    * r" w9 q% x) Y5 q( D. X* o5 ]/ n
  14.     /// <summary>6 f9 \! Y4 @- B. j9 _. J
  15.     /// 离线消息- `; n8 G2 k1 u( O
  16.     /// </summary>1 \0 n: v" J# q8 y5 d
  17.     public class MessageInfo
    " f' S: {+ r; i
  18.     {
    : x+ }9 p& c# c' L: L
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)) s! E1 T* p+ {1 I
  20.         {3 i. b& _, ?  C. r
  21.             MsgTime = _MsgTime;  l* F0 J) p4 V! m
  22.             MsgContent = _MsgContent;
    2 ~/ m6 s; I+ E: r) p3 E" t7 |
  23.         }
    6 {* d8 Z1 @- ^1 u+ V, k& J
  24.         public DateTime MsgTime { get; set; }
    3 L2 o" e! J1 m' p
  25.         public ArraySegment<byte> MsgContent { get; set; }
    7 F4 _  X0 O2 P- F9 B" o
  26.     }* J; b. P( S: M% m, p! j3 K

  27. ) [" C& Q: [* T( x
  28. : L+ S/ H3 N2 K7 V0 U& F, Y5 m/ A, s
  29. ( j1 j! d* {9 Z5 d$ V$ I
  30. " w, |- V, ^. j4 v. @
  31.     /// <summary>6 x0 W# \1 e- F4 X7 n; n. k! e/ }
  32.     /// Handler1 的摘要说明$ b. C: U" b+ k
  33.     /// </summary>
    + F' y0 T7 n8 {$ c3 t7 d( F
  34.     public class Handler1 : IHttpHandler
    6 D$ v$ B/ L5 m, l9 R5 n% T, A+ ?
  35.     {
    ; F. r( o) }& T( c
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池+ T8 S0 a. j5 D7 S' B7 x$ v6 s: }
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池+ ]# V; a+ @3 N9 [2 ^2 K0 g
  38.         public void ProcessRequest(HttpContext context)9 {" j( T- b5 u7 h
  39.         {* l' u9 ]! ~" n1 v% R6 j7 b
  40.             //context.Response.ContentType = "text/plain";: C8 L6 y7 I% ?1 \0 g
  41.             //context.Response.Write("Hello World");
    + h6 k- ^4 A% m1 j1 {9 C
  42.             if (context.IsWebSocketRequest)8 B& m8 H) T  X$ h+ Z) i
  43.             {
    4 [5 K( N9 s0 @1 k! s" }5 c
  44.                 context.AcceptWebSocketRequest(ProcessChat);# z3 F  ]6 G, }8 @0 \- [
  45.             } 8 V2 V& n% A, \) n! F/ G! p  f
  46.         }3 f) o; E7 A) l- j' h/ P

  47. 4 X# w3 X- H: E# ?+ N
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    ; K' c" q; U5 y- ]% \: k4 Z7 o
  49.         {
    4 ]. @8 u3 p8 B' P# S0 V5 @
  50.             WebSocket socket = context.WebSocket;
    5 Y) G( N- e, _; q5 Q4 J- y
  51.             string user = context.QueryString["user"].ToString();7 q2 P: \# f. a$ u8 b' e: |0 V

  52. + W: A3 f* z# g* [  R
  53.             try! L' Y; q# {" ^: t
  54.             {
    , ?) p: T& }- P& [' U: x7 W
  55.                 #region 用户添加连接池1 B! p# o7 M% x1 z# ^3 ~9 K3 R
  56.                 //第一次open时,添加到连接池中
    . G1 q  x4 m; V* G3 V8 e) d. }
  57.                 if (!CONNECT_POOL.ContainsKey(user))( P6 P8 y9 R$ z3 d
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    + G( b0 B  X6 d7 M. t
  59.                 else7 [! o. E% x0 B( n/ z- B
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新0 f) q+ k& \3 S' d
  61.                         CONNECT_POOL[user] = socket;# @$ Y3 e9 t+ v) u3 `6 o* p  X
  62.                 #endregion( ^. V- ]) X% S* @$ H! k1 l5 x
  63. 7 o5 X/ p7 g) h$ c8 L
  64.                 #region 离线消息处理
      s$ ?. W- e, A2 P. n: k
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    7 @* w" a$ ?) q" H9 k+ q8 I
  66.                 {2 z8 R& Q# W* }) Y5 w( F. b  Q
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    ! u8 u# A- k' j+ B- |: \- j9 \1 [
  68.                     foreach (MessageInfo item in msgs)
    / L" `2 q2 B, L  i; n5 v
  69.                     {
    2 x. }9 L5 h% n$ e% a; F
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    / }- g/ O, J' h3 f$ L; F; C# L7 [( M
  71.                     }/ L  c/ H7 w1 v: M4 t9 D
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    6 {8 S1 b* w+ X! f1 S% {
  73.                 }
    $ g8 P8 Q8 P& W$ |( _, q9 z
  74.                 #endregion  T" T0 S* w, ~4 \/ {: |, N& j' b2 j
  75. # r9 x& x' y: k  P; @% ]+ N" A' W0 c3 H
  76.                 string descUser = string.Empty;//目的用户
    ; Q3 P2 P: d% Z, n
  77.                 while (true)
    / w+ ?6 r" O; v1 k) Q- Q, P
  78.                 {
    $ I1 D4 c& ~# z5 c; ^, C' c
  79.                     if (socket.State == WebSocketState.Open)0 Z, [3 F1 _$ I- j# {$ P
  80.                     {
    0 N$ D5 X0 _5 d! `2 }
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);: q8 \$ g% M' L+ F) R
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);+ T$ b& d4 R8 q5 J
  83. / a" @  D% J8 ?( @7 a3 H! G7 M; h7 h
  84.                         #region 消息处理(字符截取、消息转发)4 b* X6 s6 y6 [/ X- b. P6 \
  85.                         try& I* k- E1 o) p' o  t* s
  86.                         {
    $ B+ n# s4 w) \% X9 l& X
  87.                             #region 关闭Socket处理,删除连接池. ?) J7 q8 u3 n7 B
  88.                             if (socket.State != WebSocketState.Open)//连接关闭7 T' u; m  i5 @) J3 `( K
  89.                             {
    7 y4 L2 j  A0 C1 x
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池2 [( ?; o: I7 h1 e
  91.                                 break;3 O$ Y$ V0 X% e. k$ O
  92.                             }% {# e, y) @; l" [
  93.                             #endregion
    ) w- u1 o6 a0 e, f* Q

  94. . k: W0 ~: f: ]/ H2 |: z
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息: X6 [- b( u" w; w
  96.                             string[] msgList = userMsg.Split('|');
    5 s( D$ a3 ~! _' j4 H: S/ F' d
  97.                             if (msgList.Length == 2)- {' _9 C$ p/ a1 Z) T+ K# c4 J
  98.                             {+ b5 O4 K+ f, C' u$ l
  99.                                 if (msgList[0].Trim().Length > 0)
    & l# I7 _4 j) R$ s. W) }
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    " C- E: T9 t. M" ]  Q$ v/ z  s
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    : O0 B+ {: f& Z/ i* @) S
  102.                             }* p* B  p- X% A7 @3 D: E% x
  103.                             else, n* X. p  f0 x' u" ^- ]
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    / w" t8 E- M' [
  105. % o& F& v( A% q; ~8 T  O
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    1 u2 C! b: ]2 Z- z  G
  107.                             {
    + C9 v- J* ?& K" B
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端' |5 {4 m0 [8 ]
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    ! }' A+ G$ p3 t2 l  G9 ?
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);0 f2 E0 m/ C2 c" y/ o: j$ H! q
  111.                             }
    ' U2 [& v+ z+ |& A2 m1 h
  112.                             else
    ! [% q) w, G7 {+ R! {; q
  113.                             {
    , C- G: E- Z6 r, }8 |. l& x
  114.                                 Task.Run(() =>
    - K6 b( Z. A1 c! z( l/ U! ?
  115.                                 {
    4 g% T% M' Y4 O# d4 R2 T6 U2 J
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    . E4 D) M* r5 W# t7 z
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    % Z% `' [' r$ v
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    ' C. [2 K! `% e5 }) f6 U6 m
  119.                                 });, K: T; x+ x* I) T! \$ ]7 r* o" u
  120.                             }- U& e/ g1 h. d
  121.                         }. [' v7 s6 q4 }$ d2 L8 v
  122.                         catch (Exception exs)
    & `( M, u' G1 O: P& H3 }
  123.                         {. W: Y" Q- y. ]; q% n8 B2 \8 l5 \
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息' `+ X  \$ H7 n1 E( S# x  Q8 U& r
  125.                         }0 [# G  B! T9 Q
  126.                         #endregion  e+ a& V/ q; l8 X1 s) z2 ^
  127.                     }+ x$ F4 f4 u9 |" E/ w) N0 \( o
  128.                     else
    8 P4 @# m- ]8 n) Q( q
  129.                     {
    7 Z& s! _0 B; Y
  130.                         break;1 L* V+ k" v! G/ t
  131.                     }
    # J& `. h% g/ z2 ^, v" l
  132.                 }//while end
    $ [1 F- I; i" I/ \( v
  133.             }) c( z& j4 ?: o
  134.             catch (Exception ex)7 K( Z8 q9 d2 Q, h
  135.             {
    6 R! U+ w1 o3 D7 ?
  136.                 //整体异常处理- l/ E9 m( \1 J, O
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    : j( f$ e5 i. ?$ J1 A
  138.             }
    9 M- R1 v( ^  {6 R) N1 T
  139.         }6 T! U! b; o5 i& z' M
  140. ! \6 q& B" B' G( I, r1 U9 p; Y3 Y

  141. & O! b5 E6 Q* I* v! v& w8 D
  142.         public bool IsReusable
    ; H, }) c: b; y# q+ i
  143.         {
    ! }( m7 `1 g& `; U+ A9 V" r
  144.             get
    . b6 D* _5 g6 I# ^0 Z4 ~
  145.             {
    ! p9 W2 R9 J6 }: h1 m2 Y, m
  146.                 return false;3 t3 z% V" z% g, K3 a$ z
  147.             }- e0 a! p: ~+ j/ A4 D/ N7 f
  148.         }1 w+ T! s$ l$ {5 Q4 |/ |
  149.     }
    4 v& V: J5 v, n
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
/ j6 I8 C7 e% W5 d$ K' \: a
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-3-17 20:19 , Processed in 0.083844 second(s), 22 queries .

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