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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

& u  x1 `; u3 _$ g5 X/ z" s
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;. k5 S3 _- ]  D3 [
  2. using System.Collections.Generic;; J2 r( e) l, H
  3. using System.Linq;
    ) C* M. D; Q4 n  C3 O
  4. using System.Net.WebSockets;! q1 V; }" ]9 C  @, {
  5. using System.Text;! `1 ?) x, }! w+ [# l& }0 F2 A& b7 X
  6. using System.Threading;' u7 ]4 Z8 T7 I8 K  N8 p# W8 J
  7. using System.Threading.Tasks;
    1 ^. s( K  s8 w
  8. using System.Web;  p, i3 y5 l# R5 c0 N
  9. using System.Web.WebSockets;
    ) w% R, N9 U/ B! d: Q) Z
  10. ! d2 E3 t$ X! E/ O  Q: R2 A) t

  11. / }. B3 Z; o0 K; K
  12. namespace WebApplicationWebsocketHandler
    5 ]4 P8 ]1 N" |; s
  13. {8 C8 H; e8 s* L4 ^, k' O) P
  14.     /// <summary>
    5 v8 {+ W5 U& n8 D
  15.     /// 离线消息8 E" q1 z3 b# |/ |: N
  16.     /// </summary>+ i  x; O( C- t' }$ Q: u; E6 W
  17.     public class MessageInfo
    9 M& v' t" s8 i" ~" x2 ^
  18.     {
    7 @' V# ^! O9 A4 W
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    ' C% ]! F: Y$ h  Z& M
  20.         {
    " i# o6 z- f& ]/ @8 J( U' e$ k. ]
  21.             MsgTime = _MsgTime;7 w9 O7 d7 Z5 E$ H) |5 u5 o
  22.             MsgContent = _MsgContent;
    - h/ Y* L. v! Y( D$ r9 \6 ^) B
  23.         }' k8 _1 Q/ O- G# ]# I) {
  24.         public DateTime MsgTime { get; set; }$ t- g. }2 u% u, x; F: Z! C
  25.         public ArraySegment<byte> MsgContent { get; set; }
    ! j2 v2 m7 k8 N( {; D* N. _
  26.     }( Z+ M' }8 h' u! c8 [' z: R

  27. 5 `9 E! }# t8 @& M. C" u, I
  28. 8 g! x+ k% m* c6 G% d/ B; v, a
  29. ' T) h: d6 x  \: W. i

  30. ( N( J4 i  P+ ]$ @
  31.     /// <summary>! b. o7 I& I) ]5 S# U
  32.     /// Handler1 的摘要说明- j: y. M5 A  \
  33.     /// </summary>1 Q, ^4 k: [& M8 U9 l
  34.     public class Handler1 : IHttpHandler
    % L5 A, _0 B+ w
  35.     {( M3 Q+ A( R" n: }, }! L
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池$ ]9 z  ~5 T; V  P  C
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池4 A# C! J3 G4 j" ~4 K9 e, j4 D
  38.         public void ProcessRequest(HttpContext context)9 ~* C8 l& W% q( \' s
  39.         {/ D$ t* V  E7 G  q! g4 u0 H
  40.             //context.Response.ContentType = "text/plain";
    ' j7 ?3 M7 g! M# B. T# v
  41.             //context.Response.Write("Hello World");
    + w7 y& V; `9 j% b# {
  42.             if (context.IsWebSocketRequest)
    / o# b7 p5 d6 j# g+ i5 v3 I
  43.             {
    $ y: Q7 h; J8 g
  44.                 context.AcceptWebSocketRequest(ProcessChat);# T5 ~9 j: M4 D/ }) F3 X
  45.             } . F# |: Q$ Y7 F8 Y. h. e) c( [  Q
  46.         }
    1 }) i4 w& u# J! Q; S

  47.   S% u& y+ [5 Y
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    , }) N7 w4 S) V
  49.         {
    " M: v/ t, d# Y+ _
  50.             WebSocket socket = context.WebSocket;# \5 l# ]+ `0 I
  51.             string user = context.QueryString["user"].ToString();
    5 [" \2 V, r& l' p8 j! h; x
  52. % Y1 I- e% m. {5 b: ^
  53.             try
    + T, U8 |: h; g) n" A: o2 g/ c/ ?
  54.             {! z$ Z( Q6 a% z7 i
  55.                 #region 用户添加连接池$ O: |1 F, z* {; a
  56.                 //第一次open时,添加到连接池中
    ; j7 B% e1 C! Y$ b1 y6 D5 }
  57.                 if (!CONNECT_POOL.ContainsKey(user))0 _' o, e, W8 [% j8 i$ W$ T; T8 ?+ R
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加6 E" q6 C' u/ S' v3 ?9 `
  59.                 else
      y, r- p2 g' [  G, l4 f3 `# \
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新: H, A% k5 x2 |! U
  61.                         CONNECT_POOL[user] = socket;
    0 V5 A9 [5 @) k- u- Z
  62.                 #endregion
    ; X# d; y5 ?) U' M1 L. ?  |
  63. $ ?8 b; P* K$ y) V" B- v- P
  64.                 #region 离线消息处理4 T, f9 {6 v2 [; V7 m: @
  65.                 if (MESSAGE_POOL.ContainsKey(user))! v) r, R& v) W6 ~9 e
  66.                 {/ [* `# `/ v/ O
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];  q1 j/ O+ S0 ?! k8 x, k
  68.                     foreach (MessageInfo item in msgs)
      \. b( s1 u& a+ r4 n8 Y
  69.                     {! }4 Y) J7 L2 Q: Z  G* m/ L: u
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);4 K/ v1 {: M; q( ~3 ~
  71.                     }
    # D1 R0 Y  N: b% Y  e* I
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    0 {3 q& W& r4 q4 q, {$ W! J" ~8 a
  73.                 }3 W' C) }) |' _# j
  74.                 #endregion
    % k8 D  y5 G3 I+ Z) Y6 f
  75. ( }1 D" B8 S, m* I: M5 H  @
  76.                 string descUser = string.Empty;//目的用户
    4 f* T: d( {: ?6 S
  77.                 while (true)7 f5 M4 A' K9 ^# `2 Q1 M. [
  78.                 {
    7 w% E& m% _  R0 y2 c* n: @1 T
  79.                     if (socket.State == WebSocketState.Open)
    9 P0 C/ q: K8 F* e
  80.                     {% L! K. `) G/ V' {# F  Y
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    $ U* e: G% q/ {" G9 {- j
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);! D3 ?$ H4 D! L; y# @

  83. % t# {. b6 N0 @
  84.                         #region 消息处理(字符截取、消息转发)
    : W! `, L* {, g+ G; R6 \
  85.                         try8 O9 e+ Z8 O6 \0 i3 u3 [$ h8 w/ e
  86.                         {5 `+ N" o. `; a. a. \4 d. c  ?
  87.                             #region 关闭Socket处理,删除连接池( L0 P3 U) O( \. x! s8 i2 l4 u  F
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    6 V3 K2 K3 e! C8 d6 D; W5 N, ?6 J
  89.                             {
    ) s" v( x: D/ ?* U
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池4 Q7 @$ w2 V6 ?% n% j9 |  e# t; g) Q+ x
  91.                                 break;5 M- d6 J8 h0 L  R8 m
  92.                             }0 `4 G2 I+ ?( U- Y2 F
  93.                             #endregion; b/ i; _* r# e# K& Z2 |; D
  94. ' }8 ~& n$ c2 t4 W. `
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息3 J) Z" L. ^1 X
  96.                             string[] msgList = userMsg.Split('|');. L: @) }8 j1 Y# e$ P  r& z& K9 S+ V
  97.                             if (msgList.Length == 2)
    , m, d4 o) N" d1 I5 o( K: A$ X
  98.                             {  F6 f: s5 P4 W+ A9 C1 O
  99.                                 if (msgList[0].Trim().Length > 0)2 ~' O! s) ], _
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户2 ]9 K* A) H. O4 ]1 q% u" G
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    / X: ?4 X6 L) E
  102.                             }
    % Q$ _* U! M: u- n
  103.                             else
    + u! ~9 K( W% \  t7 G9 t7 {& m9 _0 B
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    ; e; n  A9 t* |

  105. # R7 I% ]# k# g' r& e) R
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    9 [8 b6 ]: ~% Z
  107.                             {) ]5 ]! v6 H, M) l: T8 j( A0 s
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端  ^, h: w9 L% ~
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    + i( v$ s# S' N! w
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);8 e2 h. l! U# Z/ e5 }; C! b
  111.                             }
    " F' {( z7 B- Y: s3 E0 y8 B1 |1 [7 Z
  112.                             else
    # N5 a, g# V7 C0 l) c* n5 }
  113.                             {
      V/ T$ ]4 x" u& H
  114.                                 Task.Run(() =>
    " n+ }& h4 I1 T" w" P
  115.                                 {
    : G1 p* R! }( g5 q0 `  J; c
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    - X! _6 X: k/ `9 _
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());: z: W% h& Y! X2 ]0 `: m% }5 m
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息' g% l" l6 D9 t( A/ f
  119.                                 });  C, m+ x2 l: l, G  r6 l  p
  120.                             }
      K' m; u, R) Z$ n, i3 Q
  121.                         }
    8 r5 V' ^) G# v1 z
  122.                         catch (Exception exs)+ K4 t! ]9 v8 q
  123.                         {& K  s% A- B$ C8 Y, S4 E
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息2 n8 f9 x0 p9 A5 {4 c: d* D  B( K9 d
  125.                         }
    ; v! n" S6 x9 O4 T: }; A# Z0 V
  126.                         #endregion
    $ W  r- E% J. Q6 @0 h2 w% {
  127.                     }% k+ d0 Z# p% l2 A
  128.                     else
    / L! Q8 ?% F: `! ^: ?; L3 Z" g  q
  129.                     {+ x9 i8 d+ ?2 e& r8 H; A, K
  130.                         break;; {! W8 d$ C: \1 Z$ t0 f3 V4 K
  131.                     }( y8 N3 v' H9 C, n2 t1 F; p5 m
  132.                 }//while end
    0 v; G0 X+ |( l1 E9 l" s* O6 l. l1 c
  133.             }& \, p3 ]* g/ J! d& _! l1 a3 O
  134.             catch (Exception ex)3 x/ _) V4 W( N7 q5 g" \& L
  135.             {1 {9 u, e8 x$ o" g# g9 J
  136.                 //整体异常处理
    & G, j% \% T* t5 ?
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);/ X0 v4 N/ ]" c
  138.             }% j1 z% m- C2 _
  139.         }% T& U3 ~' s* S3 Z3 [  r0 E# p# z
  140. # I+ L) X0 R2 p6 Z- J# o% ^
  141. 2 \5 x1 `* @% ?
  142.         public bool IsReusable
    1 [" y/ Z) N8 Y: Q
  143.         {
    - a( x9 D8 ]! g$ z1 n! Z
  144.             get/ a1 B' ?3 v- Z  T. G- B
  145.             {
    % u) |7 K% S- b: l# L) B0 {
  146.                 return false;3 H! {( l, t: n* c
  147.             }
    ( i  B4 C2 N9 E6 n
  148.         }
    8 b, P0 [, \4 d8 ^6 X9 j* A
  149.     }* ?5 j! e. _% R# ~5 d$ p" ]1 z
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
* Q# l, L: K, F  H2 Y
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-6-20 01:33 , Processed in 0.064417 second(s), 22 queries .

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