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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
4 K2 R; o1 I. V
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    ' v9 l- I/ ~( x! _
  2. using System.Collections.Generic;: d$ V. ^5 k$ I7 E6 D
  3. using System.Linq;
    6 b8 a0 _% i4 F: B
  4. using System.Net.WebSockets;
    5 _: V, C7 N# y4 f: |9 A
  5. using System.Text;: h# I; u/ H$ h9 b. n% o
  6. using System.Threading;
    7 J' Y, G8 W0 }7 ~) V8 c3 W  B
  7. using System.Threading.Tasks;
    1 X3 R9 W* B; Y
  8. using System.Web;4 [$ R. Z% S) J+ ]8 f, O, X- n
  9. using System.Web.WebSockets;
    0 @4 I1 W  d  b3 w& a

  10. 1 R+ w; h  g$ x2 w  w- K
  11. ; W* k( T: g/ C6 S: ]( C
  12. namespace WebApplicationWebsocketHandler/ y; X- y5 Y% ~0 R) N
  13. {* ~" P) m$ X  P2 @
  14.     /// <summary>
    # f5 j* `( @, D% O* {" d& E+ T2 Y
  15.     /// 离线消息
    # p+ r" S* U) m) Y
  16.     /// </summary>
    / R/ t% s# c% e& |8 J6 R* l4 y7 e
  17.     public class MessageInfo
    . q  m; K! Z+ B3 O5 {
  18.     {  _) K0 u$ g$ M& a" r& h
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    2 g- C- [! A' o0 x' u
  20.         {& l# o" _) ~1 m
  21.             MsgTime = _MsgTime;
    4 n! Y/ A* G/ K6 j2 y+ e5 u
  22.             MsgContent = _MsgContent;
    6 O# g  @6 c% _, G$ L# Y7 V
  23.         }7 `' f7 A; C$ D$ S2 Q$ g
  24.         public DateTime MsgTime { get; set; }& n- o* T& y  F* K9 c
  25.         public ArraySegment<byte> MsgContent { get; set; }( O% z# r6 p8 |9 ]- g
  26.     }
    6 A7 f% Z) m$ u- U
  27. 0 W. v2 @' s% n2 r. O# O: [
  28. 4 [* A: w* a4 j- D
  29. ! K9 z5 Q' k6 q* \8 R, g1 ?$ S- W
  30. 9 y, A2 b1 ]2 ^* p( P5 S
  31.     /// <summary>9 p5 v7 _; G3 Q& e3 k0 ?
  32.     /// Handler1 的摘要说明) z0 w1 @. P) c, b2 o3 j! G
  33.     /// </summary>
    5 B: O' \- O9 T: S+ y! R
  34.     public class Handler1 : IHttpHandler
    1 a# y- |* k3 L0 C" e- S7 e/ _4 u
  35.     {
    " M( k7 H, e; |
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    ( `9 P- T& K1 Y7 C
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池- L: v0 y7 j# v% Z9 q3 R3 {* d
  38.         public void ProcessRequest(HttpContext context)
    4 C# Y& N0 [% h' r5 t6 w% M, H
  39.         {* Z; E7 q/ q6 j
  40.             //context.Response.ContentType = "text/plain";  g* h2 d; [5 C$ E: L) K; |
  41.             //context.Response.Write("Hello World");5 q2 f: s1 t) q- h& X1 Q4 q- v
  42.             if (context.IsWebSocketRequest)
    1 K( r6 \+ A# a) R- G( B; H: A' y% x- G
  43.             {/ ?" f" i% T" {1 D
  44.                 context.AcceptWebSocketRequest(ProcessChat);- ~1 \' R  |) r
  45.             } 6 p- N0 U( v  t0 M- U
  46.         }
      p# M& ~  o$ r/ X0 X
  47. ! x; R6 |3 `, B5 C3 L; Y
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    : E5 H/ [, e" N0 s1 a% @/ I
  49.         {
    1 I+ D5 V& R- z; I! \# A
  50.             WebSocket socket = context.WebSocket;7 P) i$ e' Q( h/ i3 t4 F$ U6 p
  51.             string user = context.QueryString["user"].ToString();
    & V  P$ C6 C+ K2 j% O9 r% ?9 G- L- G, ]8 j
  52. * c) r$ q0 U8 s
  53.             try
    * r2 D# l/ l6 N. x; j
  54.             {
    + i: }$ ~# p4 @; ]8 G
  55.                 #region 用户添加连接池6 R6 K- o& r5 n- e4 B" \' P
  56.                 //第一次open时,添加到连接池中! \4 ~! Z# \: y7 b6 w
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    $ |5 W& _' r! U# U7 q; u# o
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    # \. Y% r% @- f
  59.                 else
    ) R6 J1 M, n9 o0 c0 m6 x0 M; q- S
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    * M" J2 ?4 V' {, s! B1 s3 ^
  61.                         CONNECT_POOL[user] = socket;+ m; q) k# h0 ]# ~# D3 O
  62.                 #endregion% A" f" b8 {+ M: O1 ^1 V

  63. 0 A2 N2 n& o9 s4 B
  64.                 #region 离线消息处理
    * A% P8 B2 Y" j" z+ W; ^
  65.                 if (MESSAGE_POOL.ContainsKey(user))- L& A" a3 n3 V. ^) T
  66.                 {, S" E, G6 V* f& T
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    ; S9 L2 H8 _! w5 @
  68.                     foreach (MessageInfo item in msgs)* C3 S0 t% |' A& ?
  69.                     {
    3 Z9 F  ^' B4 G* T
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    + [) j( h% O5 h! ~: d/ c! j* t& R
  71.                     }+ y1 D  e7 m: h6 }
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    $ i4 J3 D9 v1 ^. n$ S/ v/ f$ H
  73.                 }
    8 X0 [0 K4 C8 n! n2 ^
  74.                 #endregion
    7 Q* D& B& V0 _3 _
  75. / X  C# B( M! _# F& I8 y. x
  76.                 string descUser = string.Empty;//目的用户% W9 d3 k; [( ?. A7 A1 o$ ?
  77.                 while (true)
    % y  q/ o- _. M+ C$ e7 L5 U
  78.                 {
    2 @; p$ D3 y1 K: U
  79.                     if (socket.State == WebSocketState.Open)
    ) [$ A  W, B) _
  80.                     {' b+ ^, b+ g2 W
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);- v  o9 ?7 d6 \' S: h
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    % ]; W( L9 {$ v

  83. / m3 D( X9 Q7 J4 N3 P+ d2 O5 S0 J: e
  84.                         #region 消息处理(字符截取、消息转发)
    3 R1 D' \2 S+ C% @/ [" e, d
  85.                         try. }5 u4 T: U" j! `
  86.                         {! Y! F' y- k, n/ t' j6 U' h5 F/ \4 C
  87.                             #region 关闭Socket处理,删除连接池2 }' B( l3 f& Y$ [3 b
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    6 e, j! K3 ~6 P
  89.                             {
      J# ]; `1 D) D1 D
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    8 N+ }* W4 _! p: W
  91.                                 break;
    0 [$ H6 d' R) K8 E+ o4 y; @+ d6 ^0 q
  92.                             }
    ! e8 _) R% l/ o9 m4 \1 x  W
  93.                             #endregion
    & ~# ~8 D' }/ g# `% ?
  94. ! d' U5 ^: h9 a$ A
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    ! q2 C1 t+ w, I- V' {" X
  96.                             string[] msgList = userMsg.Split('|');
    4 ?9 N! Y# e8 m: S
  97.                             if (msgList.Length == 2)& P; P" l" y9 P. v( F
  98.                             {
      A9 h& K1 Q# x) ]  a- ]
  99.                                 if (msgList[0].Trim().Length > 0)
    " E6 Y* f0 f( x, t  a+ j8 H/ C* D0 G$ V
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    2 }4 m$ v5 S' d: K
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    - L6 D" b; ^. p# A3 D
  102.                             }4 N# w# c7 G0 f4 A; [: y9 l3 i
  103.                             else
    : a: s- {' s/ O3 b  L
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    . o; ~, ?0 M& e/ ~- e% B
  105. ' V' w# v* v. h& l/ F! ~+ s3 v) C
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线8 @9 H5 A. A5 @7 D) z2 R
  107.                             {# b" A0 v# s/ D. @
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    9 W" q& [1 |; V- h. X( L1 i# L) c& \
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    0 ~: p, k. a' G/ B6 ~
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    : ?4 I  Z# i' {% L) i
  111.                             }$ b" J* F4 f& X3 E9 O. a! E% I  M
  112.                             else. v; j7 _/ S) V* i
  113.                             {
    * P1 b. e' M$ Q1 Q9 q
  114.                                 Task.Run(() =>8 |0 Q+ p) G- T! x, l
  115.                                 {# P$ E; p5 ?6 }% l0 [( b
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中: `4 e* P" R/ I# o+ [5 \
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());0 Y+ X4 a- l7 C/ I* ]+ t1 z
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息3 i: N3 i' [& x2 ?1 `' C) O$ {
  119.                                 });
    5 y, e) T: N8 z
  120.                             }
      z. G  j, m2 N+ K7 {
  121.                         }1 q- l% n: G" N& i
  122.                         catch (Exception exs)
    + d0 P* B; k4 o9 n
  123.                         {
    , ^; [2 C' G: {
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    ! T! H# E" x: a1 y) `0 w) s
  125.                         }
    1 z3 Y# O" n  U8 S
  126.                         #endregion
    : d) D7 v2 E! g% }# T' k& j
  127.                     }) y) ~2 P; H6 X. t# z1 Q
  128.                     else
    5 @2 D% D( f2 w
  129.                     {6 r4 b" Q) [' N3 h0 x
  130.                         break;
    % ]8 v4 ]  I" ~# ]# r4 A
  131.                     }
    0 `& f( p! v; v3 ^8 d
  132.                 }//while end
    2 D! T. I$ _6 s8 e& V, p
  133.             }2 Y$ a% f% n& D; \1 n- ^- \( r
  134.             catch (Exception ex)$ v9 }+ O. u& A6 {8 x0 P
  135.             {, }2 U. {# N5 R+ q
  136.                 //整体异常处理. c5 |  `% @$ \3 n: s
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    - s, M, u. x* p' [
  138.             }/ @1 @7 A: L5 t$ [9 K! v
  139.         }
    + m1 A. h4 Q0 C% K- e& `
  140. 3 i, ^% Z5 I/ c
  141. # s6 A$ g1 b, s2 [* a
  142.         public bool IsReusable
    ) |3 F2 B$ K; |
  143.         {
    , L/ p! q; ~+ A, e* j( I! f" U) C6 t
  144.             get( D1 e1 U! a7 q- }2 o; \1 m
  145.             {
    9 R# D2 E+ m& M2 t: w# O
  146.                 return false;. _2 s8 O( Z8 W9 q$ }  x7 P3 D: v
  147.             }" T" h+ {- o4 Z/ ^# D4 ~- S3 N
  148.         }: j5 ?7 v" O* E& |
  149.     }
    / B8 J( F' e4 n
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
( ]" o- y3 J; V1 i' D
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-9-21 05:17 , Processed in 0.057916 second(s), 22 queries .

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