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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
& A2 Y4 w5 G7 Z# O' }8 z# H7 k
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    - D3 l: A: A; d. e
  2. using System.Collections.Generic;
    0 b' `) @, D3 z7 V  a
  3. using System.Linq;7 X* \0 y& r( v3 I+ C# P3 [
  4. using System.Net.WebSockets;
    % e$ ]! R( d- F5 _
  5. using System.Text;
    8 T1 l: J; {' ?: W6 j) V
  6. using System.Threading;
    ; a1 i4 x9 K* D8 N/ _$ M7 v
  7. using System.Threading.Tasks;
    - X0 g3 E5 x" ?" l
  8. using System.Web;% P& [* Q8 R9 v2 u6 d
  9. using System.Web.WebSockets;+ V: x/ l2 z2 B/ d1 S

  10. ) ?6 r& ~  Y& I# l
  11. " m# b3 f0 W. I, f3 @
  12. namespace WebApplicationWebsocketHandler6 p4 o# R9 p3 c- b+ R# w3 \
  13. {% w! P+ V) |2 [5 f9 `! c+ i
  14.     /// <summary>9 Q/ n+ @/ G+ x' Y8 U
  15.     /// 离线消息# [8 h8 p4 Y0 S6 e
  16.     /// </summary>! J0 H3 c2 ]) s; @
  17.     public class MessageInfo$ {+ I) k( O) {
  18.     {
    ' T7 j3 G( r9 [. ?
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    3 R2 T# t, O$ e2 }) a; T/ d
  20.         {
    # e& F+ g3 ~* i/ F9 r$ J8 g
  21.             MsgTime = _MsgTime;0 ~: q8 B; U* Z) t) C" X
  22.             MsgContent = _MsgContent;
    . O7 \$ }; q) `' v3 G- X  ^, j
  23.         }; |! m  \9 i  j& e1 r
  24.         public DateTime MsgTime { get; set; }
      T- y; B; u4 k6 M* T  N# Y2 G
  25.         public ArraySegment<byte> MsgContent { get; set; }
    . |- \/ C0 O1 {- E* l
  26.     }2 G8 g5 v) u; M5 S7 s* v

  27. $ ^. D/ Y) ~3 L1 v# h1 f

  28. 2 k. Q" J$ n/ h
  29. % s" R; U4 `( G4 C) k$ Q% t: {. n
  30. . C2 [: C4 U+ O0 N- K
  31.     /// <summary>
    : A4 u: W- n4 G7 [# d6 f3 t
  32.     /// Handler1 的摘要说明
    9 P) M0 ?9 U/ S
  33.     /// </summary>9 S" U. c$ r7 ~( j1 }
  34.     public class Handler1 : IHttpHandler
    1 @5 g; K. m+ p5 C7 d. f4 F
  35.     {
    6 P+ `4 X! U( S- G  U+ O4 l
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    ! \3 ~. ]' m1 v9 ?, o( t" \
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池! N- r( `# B0 p% K9 H5 B: s" @# E+ ?
  38.         public void ProcessRequest(HttpContext context)( S% m. a+ s4 c3 |+ t
  39.         {
    , a4 i/ ]$ R  }! y) P! G
  40.             //context.Response.ContentType = "text/plain";
    5 d2 y; [: `+ o: `
  41.             //context.Response.Write("Hello World");
    % y: O4 K6 L9 ]/ A! U8 _3 M3 M  g
  42.             if (context.IsWebSocketRequest)& l/ H3 C3 ^1 Z  ?$ i, f# W( o
  43.             {
    7 b! q% H8 ~, \8 M" u
  44.                 context.AcceptWebSocketRequest(ProcessChat);# X$ X3 B% n/ R
  45.             } 8 |1 t8 ~5 I; U! L. p
  46.         }
    0 t; y- z- j  l; c! G( _

  47. 8 o. e; N2 p. f+ c. e6 u
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    , ?1 K+ h+ @  l+ C
  49.         {
    ' \3 Q$ D( A* H! G* ~
  50.             WebSocket socket = context.WebSocket;
    7 g; \- t7 H/ s9 P8 L
  51.             string user = context.QueryString["user"].ToString();6 e  _/ W5 {  R  y& `9 }

  52. * s6 y% x1 N& {9 @5 u) A
  53.             try3 E$ J4 G, [9 _9 C
  54.             {
      {" C$ G9 S& [. h
  55.                 #region 用户添加连接池
    2 r( \* F7 A! @& |3 b" C- Z
  56.                 //第一次open时,添加到连接池中: v$ l8 f7 R9 U! H  x8 o( G; N
  57.                 if (!CONNECT_POOL.ContainsKey(user))& Y6 p" ^! L3 G/ @# C
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加3 ]9 H4 ~  q) |9 u7 W! ^
  59.                 else
    ; {/ V/ S4 K* L6 l( a5 L, Y# R$ y3 J
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新8 y7 v% H  E$ d: }, D: W( O
  61.                         CONNECT_POOL[user] = socket;
    / I" g) ?7 |5 A7 L# B. ]; l' R
  62.                 #endregion: R$ ?& u- e" S3 c, Y3 I
  63. 5 s# q2 b0 C9 O% O
  64.                 #region 离线消息处理. a2 R) x1 `7 b  a) _  d
  65.                 if (MESSAGE_POOL.ContainsKey(user))0 b: c( X7 c: b; C- ]
  66.                 {
    ( \- r7 g* x, @3 b
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    , o( b6 B7 I  o& d
  68.                     foreach (MessageInfo item in msgs)
    : R1 [+ O6 n# N7 `7 c2 ?
  69.                     {6 l, V2 _, T( E$ d, h2 F$ @8 T8 J
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);- ], ]2 ~, Q1 F& ^
  71.                     }
    5 C* f8 \% V( r
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    : w1 u# o  O+ \- @* g
  73.                 }% w4 |# t# f1 R6 b+ J; Z+ U# r
  74.                 #endregion. C" X' D$ J. S  p0 y
  75. 2 w* Y/ r: Z0 B7 S  w
  76.                 string descUser = string.Empty;//目的用户
    5 d% k5 U$ f; A" i3 U' ]
  77.                 while (true)
    # L6 m( M( R" C
  78.                 {' Y8 A: h" y. Q' E- |' o
  79.                     if (socket.State == WebSocketState.Open)4 ~! \7 Z; }# j6 i
  80.                     {2 w7 W, O6 p! e9 _+ P& a
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);. o5 {" s9 K0 `) u$ b( \
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);  r' L% p3 l0 W! x+ ?/ z  h+ f

  83. 3 ]7 s: K) y+ d- C" ?2 Q6 ]- l
  84.                         #region 消息处理(字符截取、消息转发)
    8 `5 Z, j$ w( Y
  85.                         try: X4 A' Z- I+ n) p' V# F. P7 Q1 _( K/ y
  86.                         {$ E# `( I$ L( {$ Q, c7 s2 F( F
  87.                             #region 关闭Socket处理,删除连接池( U; u9 O/ A6 [
  88.                             if (socket.State != WebSocketState.Open)//连接关闭  v$ l% j: Z! z8 A
  89.                             {
    5 p5 h3 i3 ?) {0 F# P% w+ h
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    0 ?' C) |) e; i% v1 r
  91.                                 break;
    ) ^) P5 r& B3 ^  Z
  92.                             }
    $ d1 T. `; [  Z) j
  93.                             #endregion
    + Q: ~4 K; O2 ]1 q- K. l5 P
  94. 8 e/ t$ F& `2 U# k" i" V' b* {* R
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息# L7 R0 Q( b5 C
  96.                             string[] msgList = userMsg.Split('|');  T4 G" M7 y- g
  97.                             if (msgList.Length == 2)
    ! [6 A  @) p0 n- X
  98.                             {+ A0 M! N  g6 Y0 m; O& I5 y" @
  99.                                 if (msgList[0].Trim().Length > 0)0 j  F2 R1 C, c6 u) W6 G) f) P1 _5 G
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户1 B8 @+ v6 {0 J( V2 R
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));5 R% h! A. S+ E/ M& v
  102.                             }$ Q3 ]: _9 ^7 H/ Z7 g
  103.                             else
    * r% g4 a+ L$ N7 y7 H1 Y
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));( L5 \+ g" v3 k7 }! y
  105. . n3 C) k5 S) f2 J
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线1 c4 ~4 X$ \( I1 `
  107.                             {8 r8 g$ r# m% [! H
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端' V2 E1 q" z* |) b$ P
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)+ K3 p1 H% f1 }/ F3 F$ ~
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);/ w, Q2 x6 Z# O4 B) ]% h
  111.                             }2 Q: J3 P. T' j1 }3 V
  112.                             else* H. }9 ^2 m& Y; n
  113.                             {
    ( @+ f7 h' T! N( _3 J4 [# J& v
  114.                                 Task.Run(() =>* g) g4 ?, @2 y8 l- j7 y
  115.                                 {
    / l; Q7 a- g5 Y( h/ r
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    " W0 B! T/ o" N0 v) K. j2 M) l0 j
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());% _7 v. E) R) ~0 s, c; p+ h
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    7 I) e3 ]- n: b/ E
  119.                                 });
    ( ?7 X0 {4 ~& ^/ I8 q& O4 y' x0 ]
  120.                             }
    ' l2 j. |$ M) w; Z% s* R' m* g
  121.                         }& _/ T0 g2 s, W
  122.                         catch (Exception exs)
    " F' j( s$ H5 M. A' q' ~' y; c
  123.                         {4 \: \& E4 J$ ]+ s
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息) j7 k& ~0 U1 O) V6 I/ T. A( ~* v: r: z$ k
  125.                         }
    , p$ n" P5 C: L* |3 a0 ?
  126.                         #endregion
    ' Q4 r1 I& K- W. J! Y
  127.                     }# n* W" O  t: w5 b0 ^
  128.                     else* j6 q1 {' d& i1 k+ y
  129.                     {7 M6 j* g% T& ?. i
  130.                         break;; S" Z- _$ i- X% r; N
  131.                     }
    5 a( W2 f% k  M7 k6 {' r& z% p" E
  132.                 }//while end5 h2 h. d' z. h
  133.             }3 q5 u# X2 t: V. O
  134.             catch (Exception ex)
    9 Z0 `  ?! A1 {  l$ \6 i$ p
  135.             {
    6 l; z- C2 U9 q! t2 H4 C
  136.                 //整体异常处理5 i7 \/ W$ V$ U2 d( D5 j
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    6 C- O* g! j; e6 M* S
  138.             }% S, _6 f; @$ h- F; g! q
  139.         }4 W$ g! T9 b  y' N; F

  140. & S8 c# N8 J* d" O! B+ X- o$ ?) i$ \" [% @

  141. $ ^# d. m( e4 U$ ]. O
  142.         public bool IsReusable+ S5 F! O+ B$ C
  143.         {
    2 X0 y& [) a1 f/ w- o5 Q
  144.             get
    ! S/ Y9 u* ?- F3 Q% t9 o
  145.             {
    3 g0 K2 E/ I$ n! Y, b( T
  146.                 return false;( L( u' B1 S( X& x0 h& U( r
  147.             }
    6 ~( c: o* {; f5 o: H+ p+ `
  148.         }3 _, o) ]' b5 d5 q0 W2 U- J' p
  149.     }
    / w2 Z# Y" [6 G: d$ R! g- f2 i+ Q
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

  [" ?! L: e  |& Y" G
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-3-17 18:25 , Processed in 0.064632 second(s), 23 queries .

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