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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

1 I0 m+ ?3 e; u$ E+ g# R
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    ; k) e8 B. X2 X+ E. B
  2. using System.Collections.Generic;
    - ^) p$ k% V0 G( \( R. h8 t* _
  3. using System.Linq;
    6 E, K6 E9 N$ v9 a  E7 Z0 R
  4. using System.Net.WebSockets;
    - o8 h$ w* Y8 [+ D. H
  5. using System.Text;
    # d* V1 d  Q1 b% M, L, n
  6. using System.Threading;
    9 X4 I& N2 C% x4 ]6 `1 P7 V
  7. using System.Threading.Tasks;2 h. ~$ M! R- J2 U* H' t
  8. using System.Web;  S5 p9 y3 q" a+ \& I% X
  9. using System.Web.WebSockets;- E, G  o" p1 w

  10. 6 P3 P/ t9 G0 W; G1 L; L4 y: [
  11. ( l7 Q& ?* ]3 Z+ b
  12. namespace WebApplicationWebsocketHandler
    5 o  W% ]6 N3 |& w: j7 k2 y
  13. {
    . m& }0 s1 f1 u: N- X+ i
  14.     /// <summary>
    $ {, I; L" s5 A; j  D( d$ y2 w6 _
  15.     /// 离线消息
      |7 |9 Z5 P5 Q
  16.     /// </summary>9 \7 Z7 D4 Q  i/ H
  17.     public class MessageInfo
    : E- y6 Y7 {9 O0 Z$ D4 D% d  e0 E
  18.     {7 c, X, S& Y+ b
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    + x& U( f3 r' @$ n
  20.         {1 S" v3 E1 j. f8 K* n) ]) s+ W( w$ M
  21.             MsgTime = _MsgTime;/ f* E& E0 x( x' K2 X) P
  22.             MsgContent = _MsgContent;) G* }; e3 `3 z8 d6 F4 c( Y
  23.         }
    # x0 l) `8 D% P3 S0 W2 T
  24.         public DateTime MsgTime { get; set; }
    1 I+ L! [! u. w% o: r
  25.         public ArraySegment<byte> MsgContent { get; set; }/ R/ d  @6 _' p* F% k
  26.     }  V9 e  b+ z  b8 E7 G9 d) d- |

  27. 1 n2 r9 N# y  s0 V8 {" ?! P
  28. , T+ R) \) Q& ]* ]

  29. 8 \) q( e% f# x: t( ], z5 o9 q

  30. " v5 M+ ?4 V9 {8 V7 }
  31.     /// <summary>6 ^5 ]6 B! N& W$ E
  32.     /// Handler1 的摘要说明. z4 B: h3 s2 ~7 E& q
  33.     /// </summary>6 d/ o$ m; v3 p! `9 n' c. M8 f" \
  34.     public class Handler1 : IHttpHandler1 o' R/ _+ ~) j5 x) Q$ L# U& M
  35.     {
    $ ^! n% v3 g; o7 O# c( b
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池3 B5 n! b9 k3 e! S5 N
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池" g3 M; p4 {$ R9 J
  38.         public void ProcessRequest(HttpContext context)* a$ ]0 T' I' a4 K
  39.         {
    3 N8 u: [+ I9 H, D4 C
  40.             //context.Response.ContentType = "text/plain";
    1 ^4 h8 a% I8 \7 |! x
  41.             //context.Response.Write("Hello World");
    - v* @. Y! b4 E: K% Q9 V& m
  42.             if (context.IsWebSocketRequest)
    1 r: v* r) O/ ?- s
  43.             {
    $ Y8 c8 r9 n8 @0 |
  44.                 context.AcceptWebSocketRequest(ProcessChat);% @2 ^8 f0 {# i# k
  45.             }
    6 E4 P; G: J+ y9 Y$ y) X
  46.         }
    7 ?$ n& M' n& _* U" x# k0 J+ @
  47. 2 B0 e  ^, \& T) g) ?5 Y4 Y9 ~- H
  48.         private async Task ProcessChat(AspNetWebSocketContext context)  d" a& j2 y  c7 d9 t
  49.         {
    + }) `) |  a3 Z
  50.             WebSocket socket = context.WebSocket;
    . m# l) p6 ]8 V8 g9 C  E+ o% h& I
  51.             string user = context.QueryString["user"].ToString();( O/ X1 N9 K3 u" @* B- }6 G. [
  52. - T  d0 t6 o/ K; j2 V- [
  53.             try) J" i! o: w; f$ `3 ^: v
  54.             {0 p0 N( X; C- s, p" g! V
  55.                 #region 用户添加连接池
      k- C2 K. t1 p! Y9 T1 I
  56.                 //第一次open时,添加到连接池中
    9 |: L, R" ?9 b2 {" k
  57.                 if (!CONNECT_POOL.ContainsKey(user))! n, B# e8 V/ g  h( o% U
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加9 @# }8 V6 \7 z
  59.                 else# J: q& l. q* B
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    " z1 M/ J; y- r  y: v4 Q4 h9 B( [
  61.                         CONNECT_POOL[user] = socket;1 u. }2 D* O, |2 a& K5 p
  62.                 #endregion, _/ ^. s- s4 J% K, C# n
  63. . n- e% `/ M' D
  64.                 #region 离线消息处理$ k- Y/ S7 |" B+ A0 S) z8 X
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    0 B9 S6 b, h* q7 a. m  G
  66.                 {
    ! j$ S, B6 w& g4 A
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    ( a4 e8 A: s7 }
  68.                     foreach (MessageInfo item in msgs), H- q1 W" T7 K* w1 N
  69.                     {  H. T- g8 ~/ `: V6 y% t6 B$ i
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);% q# e$ f0 j8 J1 X; m
  71.                     }  O, h" Q* j7 V; n/ D6 M
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息% \; B; W5 G3 G/ e0 T
  73.                 }4 d% @/ \( ]7 f$ G- r4 `
  74.                 #endregion; H2 `; Z) F! {6 w* ?
  75. - u$ k7 S' w  Y) R
  76.                 string descUser = string.Empty;//目的用户6 h- b0 I/ d9 G& \( `* L- x' Z% _
  77.                 while (true)
    1 c; ~' u" P# Q, ^  D! ]
  78.                 {  I6 F' R* b8 J- m  L
  79.                     if (socket.State == WebSocketState.Open)
    2 }3 j3 R4 g5 `/ _- E
  80.                     {, @$ K* A' E6 k& m+ D$ a! |
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);8 V" k$ \  D3 U& S2 d' u
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    / q0 m. `* s( c

  83. % Y2 I9 Y7 a- ~! R
  84.                         #region 消息处理(字符截取、消息转发)
    " Z5 R2 z( `# [1 M" X6 W
  85.                         try
    4 `( X3 l3 E5 L
  86.                         {
    5 E$ Z# A' Q" n8 W$ h5 i
  87.                             #region 关闭Socket处理,删除连接池
    $ E$ d* L: ~4 s7 i
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    ' q0 ~5 _7 {9 n2 x9 f& p
  89.                             {
    2 L& e! G9 @- e" L5 Q/ B( a
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    8 u7 ^0 O" Z4 r- J8 O
  91.                                 break;
    & y% ?5 s1 a( s& T" J- Z+ q: F
  92.                             }2 V- C  s% v. R& i6 ~+ T% D
  93.                             #endregion
    . `3 l+ d5 ]& Y! {5 G  u4 s

  94. " ]1 Q9 u% y& Q- E
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    0 g, Y9 t) X  H1 J
  96.                             string[] msgList = userMsg.Split('|');( b0 S! G& u! A: W! P0 m! _) k
  97.                             if (msgList.Length == 2)) ~1 f7 S. X" ]  J! N! z
  98.                             {
    ( k! E/ ], \/ H  P
  99.                                 if (msgList[0].Trim().Length > 0)
    7 h) M6 j1 U) K1 n* D% A; d
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    ) w& Q8 w' P8 S; e8 ~* J
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));5 Y( Q$ r1 d4 ?3 g
  102.                             }- n- l; }* X. q- m& b
  103.                             else3 X. y/ [, u& L& d# v/ u, A+ J$ A
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    5 f5 Y! U7 U9 r2 Q- m* B
  105. 0 Z# i: a7 p; b- G: |% {; U
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    . K9 @$ d/ {  i
  107.                             {
    # ]  w  C2 B2 V
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    3 g. H( Q- A5 Q' U5 o
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)1 x- N8 s0 J9 {1 S/ X
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);2 J- C  K, {5 T# I9 ?# {' ~  c+ c
  111.                             }
    " O" w! k2 V1 O3 U# L
  112.                             else
      h' I4 K8 S: @4 N3 W- u) c* t
  113.                             {
    ) K' C; c+ z% Q
  114.                                 Task.Run(() =>
    " {) Q! b% e* d' h4 U* U9 x( t
  115.                                 {4 B0 p- e  s/ e3 n7 |7 N& z5 v
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    % _+ s8 ?& n3 L& c3 e
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    ; |. F+ w7 a; c/ {0 r- ?" c' T
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    - V) I5 s  b$ w2 m5 H
  119.                                 });
    ) [  E! r, u- P! z) m
  120.                             }
    " g, d; p8 |4 \8 f8 Y
  121.                         }/ n7 V  @/ `9 [5 J0 I2 k
  122.                         catch (Exception exs)
    & p) k4 N5 W! Q# @  r
  123.                         {
    2 S+ g" d7 x9 M; N3 L
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
      q5 H+ q) x- N0 `, d) U
  125.                         }" c# ~& R, M+ Z# a, ?
  126.                         #endregion
    5 x* \5 m) k! w1 H& K7 N
  127.                     }, k: `- H: A# `$ b  ?  C
  128.                     else
    / r4 _5 @6 S  }, K0 s- [- J
  129.                     {6 o" {3 E6 K- l" }; w
  130.                         break;) ^' V! Q' _1 O9 d, I% p$ W9 @
  131.                     }
    ) e2 w. t) P7 F( A
  132.                 }//while end" I& {) P* m; U$ e* v& r/ V
  133.             }
    / f" U0 S) {% E
  134.             catch (Exception ex)& L7 i6 C* k' s% K$ M
  135.             {( g: e6 Q/ i# }- A8 P, q6 |
  136.                 //整体异常处理
    $ U# l. \) V6 h" W, d0 R8 D" `
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    3 X) @. t4 w3 a) z: P! ^
  138.             }1 _' c: {- x/ E: g
  139.         }  s' z, |2 N$ N8 A$ u# [! j

  140. $ t) v; v- b( O4 g, G  ~* H, e7 j

  141. " n4 C5 V2 t( C$ J) r& v
  142.         public bool IsReusable1 O: j, b! w6 G2 s) P
  143.         {, l5 M8 q' g) C- t! j6 p- F
  144.             get& V  i0 e) w3 |1 Y3 _
  145.             {5 D  {0 u( y4 W2 d/ X
  146.                 return false;
    # }. W' E- _/ q- [! f& @
  147.             }
      f- P  A, N# }4 S( C$ ^2 Y
  148.         }
    5 |  o; m* `8 I5 ?
  149.     }
    , e& E9 F& Z- }
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
2 n/ l* N! E6 `- Q
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-3-17 20:16 , Processed in 0.057885 second(s), 26 queries .

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