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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

1 c) w0 z- \3 a4 |: l  H- N
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;; D+ W% k- r8 R
  2. using System.Collections.Generic;
    ) A% s0 e  l: q$ C6 o
  3. using System.Linq;
    ! F+ H" C5 j1 I: r/ O
  4. using System.Net.WebSockets;
    ; S. l# s) d) M# ?" O/ T' I2 ]; r
  5. using System.Text;8 A) ~* g* V4 C) A& N
  6. using System.Threading;
    & N. }1 Z# K! Q1 g8 ^
  7. using System.Threading.Tasks;$ b# n7 p* z1 H1 [& |$ y4 z1 e
  8. using System.Web;
    4 ?7 n8 V* |+ b! ]/ w
  9. using System.Web.WebSockets;& R: Q/ H1 {& \9 h3 \: _) J6 n: R
  10. % h+ n4 j; c7 e7 x3 S
  11. 3 A! s% y( C* g6 g
  12. namespace WebApplicationWebsocketHandler
    ! L) H1 B6 ^. [+ X& D7 w
  13. {( }5 {. @* D( u8 W$ J7 \  Q/ V
  14.     /// <summary>8 c8 _" A6 A7 n% `
  15.     /// 离线消息, j5 a9 a4 L% w; P
  16.     /// </summary>
    + h$ V8 D7 Q, z4 K( Y
  17.     public class MessageInfo
    ) i# |  M* b6 V, ]. ?
  18.     {; m. [4 ^* E  X6 s. e0 n
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    ' R* ^) v$ {& Y- p5 z: _8 K, Z
  20.         {, ~( f4 |& |& B1 }
  21.             MsgTime = _MsgTime;4 A2 `0 B# T! t. G% h1 b
  22.             MsgContent = _MsgContent;9 B) V: m$ F6 Y
  23.         }% o% E4 B3 T# @: L7 v
  24.         public DateTime MsgTime { get; set; }
    4 P6 a' Z/ N% v) j
  25.         public ArraySegment<byte> MsgContent { get; set; }0 J6 ^' Y" Q1 J
  26.     }' E2 C. c' a/ d2 l( }7 W0 d
  27. 5 Z, q8 f# f, H( h9 a5 O

  28. $ \+ @" Q  D4 \+ y2 Z
  29. 1 \* i$ q  i% G% v

  30. , ?' e1 E# E2 I; Y& s
  31.     /// <summary>' V" a: T  P2 Z! q' j  u7 s. V
  32.     /// Handler1 的摘要说明9 t1 p' v6 x3 }
  33.     /// </summary>
    " z! W0 ~8 y7 E% w  s7 z  N( X2 w
  34.     public class Handler1 : IHttpHandler
    0 J2 a3 k5 b: E, j$ ]
  35.     {8 @* V, K+ O* `+ i% h
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    ! d$ K, n& U" F9 l
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    # [4 A. m2 k  H: Z! |  i
  38.         public void ProcessRequest(HttpContext context); d  q- u% s: n" k( V" W
  39.         {
    . r8 ?  t* h7 v9 d
  40.             //context.Response.ContentType = "text/plain";& t1 g" M6 [" A4 V+ T  i
  41.             //context.Response.Write("Hello World");3 W0 |; M5 k6 f  a; _+ v/ f
  42.             if (context.IsWebSocketRequest)7 x9 l' B$ O8 }0 F4 {- h0 T8 C# T
  43.             {
    4 s7 ]; [8 r9 d% N4 @
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    ! Y1 h# L+ [, n2 c  G. A$ E0 R
  45.             }
    - T5 t5 O; @6 ^9 ~% Q+ l
  46.         }
    0 ]' ]+ Y5 j# H0 g' f. t. @
  47. ( ?; f5 H( p2 Q# B9 e/ l) W
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    . ^1 b6 `* Z0 Q. m
  49.         {) V& U( l3 E1 G' l6 i8 v! k
  50.             WebSocket socket = context.WebSocket;
    5 `& N4 o  n. G4 W5 f
  51.             string user = context.QueryString["user"].ToString();+ N% G) \1 r: ~' f7 e
  52. 6 X% c: p4 s  p6 F- h' I9 _
  53.             try1 a- C- V- Z3 D
  54.             {
    ( p. }/ z5 o7 X1 p" ~$ C. W
  55.                 #region 用户添加连接池; y7 q. n# g6 Z% }9 W5 G
  56.                 //第一次open时,添加到连接池中8 y5 D; G/ C7 v; n. ^% p
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    9 X" a' o" M8 F7 D& i. N4 ?8 L4 U5 t
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加- [! @; e  }1 h' w
  59.                 else
    % Y0 f/ q# B' W+ S6 L+ q! ~
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新0 W/ w7 |" W: e
  61.                         CONNECT_POOL[user] = socket;, S) L' K9 ~( T8 {) y
  62.                 #endregion% S9 P0 H6 l. f1 h$ F

  63. $ x* ?6 z# W# A: K3 u
  64.                 #region 离线消息处理4 u  j5 z4 H# H  j
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    ) W. c4 X8 A$ ~% \) R
  66.                 {
    , S7 a. S' P5 V
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];$ x3 S' w9 l( B
  68.                     foreach (MessageInfo item in msgs)
    0 M* ~% _. @0 s+ g! r. j; ]
  69.                     {* Z/ l3 O3 V" R8 v$ R3 D
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    " u! e" J0 H( |. q% K: g; c
  71.                     }4 J8 K' s% `2 X8 f5 n( c+ Q3 V
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息0 u: f* D2 Q9 \, F" T0 O& U
  73.                 }
    8 C5 G) w1 g& v
  74.                 #endregion/ s6 W) K6 e+ V
  75. 1 D3 i2 C/ w1 {$ F7 Z! x2 ?& x
  76.                 string descUser = string.Empty;//目的用户
    / ^$ t: S4 f4 C
  77.                 while (true)3 c2 l0 e6 e# A: ?) Q
  78.                 {
    2 i6 @4 x: Y6 m$ [
  79.                     if (socket.State == WebSocketState.Open)5 s6 N% l% r' [5 c+ T9 s
  80.                     {
    0 b0 I( [3 l' `3 Q- e$ D
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    5 h. C$ I% `* M2 L7 |, F0 g
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    / L/ d$ c' r( [: R0 d$ }5 c

  83. & u& Y  n$ e2 j
  84.                         #region 消息处理(字符截取、消息转发)
    + k% P" P/ g  d, w' L3 ^6 @% h
  85.                         try
    # `- `' Q/ Q  e5 a, g# F/ W
  86.                         {+ s0 W; X# u& W- i! N2 b
  87.                             #region 关闭Socket处理,删除连接池: M  h) {7 K9 r9 u4 W2 A. ~
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    6 n1 h! p& ^$ \! n
  89.                             {
      b5 ^5 t' V9 B1 m* _: k
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    $ F' C+ S- I9 t/ O9 u/ L8 z4 v
  91.                                 break;
    ' o! r+ D5 H% h
  92.                             }
    * k3 O3 C: i* n( @- `
  93.                             #endregion
    ! G( G( ~: Q1 e( i. ~
  94. & Y! u. ~+ _; ~1 H. c* X
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息  Q# w5 f: O, a
  96.                             string[] msgList = userMsg.Split('|');5 t+ ]' u1 A% U; Q" ]. a! M* M
  97.                             if (msgList.Length == 2)8 c5 `3 j" P, d- m6 r) `
  98.                             {( `/ i  [. l( J
  99.                                 if (msgList[0].Trim().Length > 0)
    # w8 [  I8 N9 z7 G7 h, B: E3 o
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    & U/ e% ?. m2 s5 n  @" z5 R
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    : m& e& w! x1 z; _1 W" |
  102.                             }2 U% W1 j3 u( T8 g0 M
  103.                             else% ~6 t: J- I) J* p1 j: U- n
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    ) W( _; s7 [. M" J( X" L* P4 o! h5 T3 ]

  105. 4 C, x: C/ x8 M( D% n
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    ' M( E- G& m9 Z3 F' Q
  107.                             {
    " B4 _% F4 _0 q. t
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端4 R) x2 D. u. y7 f5 T- k2 X0 O) i
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)0 ^  p: h" m$ H& X6 y6 B* O. J
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    ) g! o. o7 Z  ]
  111.                             }
    ) H  w% e+ C+ i, l
  112.                             else( `  z  Z, s% H8 o
  113.                             {7 k  H6 g' x, f( u+ T
  114.                                 Task.Run(() =>
    & K) x# j/ c8 C- q
  115.                                 {
    $ ]0 d7 q! q' L) p% o4 \
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    + P1 n+ [5 z, Q3 z- A5 C6 @
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());! ]5 s$ l4 M+ F7 n
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    ; |3 Q* F: p/ ]: a9 p3 X, ^& v
  119.                                 });
    ' R8 F7 Z  p3 w" U
  120.                             }7 ~) o% O0 I7 v9 F
  121.                         }
    # w) l/ B8 u$ L. z; U
  122.                         catch (Exception exs)
    : U: |4 e; @' X: W/ Y  b
  123.                         {
    + [" E& [+ h. H  J" J, i/ T$ ^
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    " \/ e4 Z& p5 K2 m8 N
  125.                         }8 N! K7 A$ t% m5 j0 `
  126.                         #endregion1 y- j2 }  ?- A: B" S  v8 m. y
  127.                     }
    " h& x5 j+ {1 W5 \
  128.                     else
    : U- K; i! x, N- k' C: N
  129.                     {
    9 `  c! M1 G4 k# \& F
  130.                         break;
    3 E2 ^* r$ V- {# q7 q
  131.                     }
    . y; m) z$ ^" {5 f7 v
  132.                 }//while end
    + I, E& L( _5 K5 Q' G* F9 @5 z
  133.             }/ [0 t! H' [7 B) l2 x
  134.             catch (Exception ex)
    7 E/ a8 \3 c3 V8 {
  135.             {- i, \4 z9 r) O( q+ }
  136.                 //整体异常处理* G* q5 {$ w/ v  k- [! G: A" e
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);( H5 i# P3 a, A1 w
  138.             }
    4 H4 g9 `2 S" c
  139.         }
    1 M, ]; }; `; D  T% d3 O
  140. / b+ a% c4 N5 R

  141. ! Y1 K- {# D; f" [' ~: @" z5 a& e
  142.         public bool IsReusable6 G1 s) `9 W9 ~) L$ t1 F* T
  143.         {7 k6 f$ M; g0 E& t4 I' ?; \* I
  144.             get6 z/ {0 N0 _/ E! M# }% n
  145.             {# y( s1 U. S7 ^6 W
  146.                 return false;
    ' e; X) v' C. M' h/ @
  147.             }% K+ ~- ?3 A/ ]& E9 W
  148.         }
    4 J2 e) \( F) K4 _0 t# ]
  149.     }" R* Y9 Z+ ?% W% W, a" l2 y/ Y/ v3 a* O
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

2 O% ]- X- I: F# _3 {
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-1-30 14:45 , Processed in 0.069519 second(s), 22 queries .

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