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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

& @/ ], Z6 Z1 ]9 z7 s7 }2 S- F
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    $ W2 d7 g; k. Q' D
  2. using System.Collections.Generic;
    2 \3 K+ X& z2 l. P- x
  3. using System.Linq;! U7 U1 n2 d+ u# {$ ]1 s! d+ I' N, |
  4. using System.Net.WebSockets;
    # k5 W, a6 S3 c8 ^; P! y' P
  5. using System.Text;( Y% Z7 P) r/ }
  6. using System.Threading;
    ( G2 g7 l7 h) I9 f" m/ g9 u! D
  7. using System.Threading.Tasks;+ e) y8 R- b. y6 F. \5 A
  8. using System.Web;
    " l. k( o, P8 `2 D$ ]8 H6 X! b# S2 X
  9. using System.Web.WebSockets;
    ! y) Y2 ]6 ^$ F
  10. " E$ L; R2 h" u* A

  11. ! n6 A, w9 c" S! j& Q
  12. namespace WebApplicationWebsocketHandler
    1 X5 e0 P1 Y2 `) [
  13. {
    1 Z. A3 C' [% d  O
  14.     /// <summary>2 e# A9 B+ i' R1 K. w; ^* B# O
  15.     /// 离线消息& n( W; ~4 b' K0 I9 e
  16.     /// </summary>& v  U( l2 `- V
  17.     public class MessageInfo- ]1 n0 r1 u6 Q* D& j3 \
  18.     {
    , B! q5 V4 o: c( `* Y
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    * B2 X5 C! S! R6 {! v
  20.         {$ A- F. P1 N8 Q9 U) `* a
  21.             MsgTime = _MsgTime;* H1 L; ]" _4 D5 |
  22.             MsgContent = _MsgContent;
    ! m- q$ W6 u7 a/ `8 `3 c  s
  23.         }  u" g% Q6 |6 j
  24.         public DateTime MsgTime { get; set; }
    & t1 H  M* ]- F. q+ B) P& ]+ a
  25.         public ArraySegment<byte> MsgContent { get; set; }
    ; g" z" _) e' ~" w8 }
  26.     }5 F) H5 d" _( V6 p0 `1 a
  27. # K2 m  Q* Q8 |7 y4 l* G$ [8 g" C. ~

  28. 8 s4 F# `: \- r3 w% M5 X1 m' f" N0 U

  29. / m, V; T) W7 [* B$ T$ m$ q

  30. ) S: A4 S2 W8 s  Y/ ^7 h' d
  31.     /// <summary>( v0 s/ w: D: G" G/ h) k( B
  32.     /// Handler1 的摘要说明
    - T8 G# e) q% o
  33.     /// </summary>
    ) |3 T& F1 \9 }- S
  34.     public class Handler1 : IHttpHandler
    2 ~, o3 o# B' r7 u  W
  35.     {
    " D, Z6 B2 g7 r
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池+ j* j" e$ b  V  T) R
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池- E" C! A, `: r& P2 W( D
  38.         public void ProcessRequest(HttpContext context)5 j6 [# p9 O7 T
  39.         {
    7 g3 G0 X% L# J  H9 L5 b2 n
  40.             //context.Response.ContentType = "text/plain";
    . v% j/ r9 N4 u
  41.             //context.Response.Write("Hello World");
    - f) V8 {% r9 V; |! [
  42.             if (context.IsWebSocketRequest)
    . E0 W1 b  p0 g0 R1 M, I6 Z2 Q4 p! h4 n
  43.             {
    " X2 o1 u) j% N- z/ P) a
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    0 T& q3 x" _5 h9 ]  i" T
  45.             } ) H( Z" z! M: x( U4 V$ x( i6 @
  46.         }
    2 W! \5 i0 m$ K
  47. 8 K# c% I% T. U8 W+ e
  48.         private async Task ProcessChat(AspNetWebSocketContext context)+ |5 R  j" r& n/ q0 ]. L
  49.         {( @  Y1 ^$ {' _, {3 o7 h
  50.             WebSocket socket = context.WebSocket;
    8 U& L* r  z% D+ t9 G5 ~: ?
  51.             string user = context.QueryString["user"].ToString();
    7 ^( e- L" L/ |8 `- e. v; \3 e
  52. ! }) \0 h  e+ F
  53.             try# H3 F7 L) b# Q& V
  54.             {
    + u# ]3 l& o) f6 T
  55.                 #region 用户添加连接池
    - v+ b. Y) ^$ i' p1 _: Q( X. v
  56.                 //第一次open时,添加到连接池中8 D. i0 X9 l, H& |1 N! d5 I
  57.                 if (!CONNECT_POOL.ContainsKey(user)), z$ J% L' Y" r$ p3 I
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    ) X5 T3 z2 s8 ]2 n! ?1 M5 |
  59.                 else3 R% z" Y. T' D/ ~
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    9 ]# J5 z8 V6 A
  61.                         CONNECT_POOL[user] = socket;; }% B, ~9 A' t9 m- X
  62.                 #endregion6 |. e, s1 h+ Y/ l0 y4 C
  63. . w4 U: a, O* l; r) s- D6 I8 g" e
  64.                 #region 离线消息处理
    6 L5 b" k( R& O  d5 v
  65.                 if (MESSAGE_POOL.ContainsKey(user))% ~8 f; x4 e) m" v3 C
  66.                 {
    $ [8 ]  c% y8 A
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    3 |* J& \/ _+ }( y8 ~& [" s
  68.                     foreach (MessageInfo item in msgs)
    ; Q5 v. q9 X, a' g5 S: E: ^5 [
  69.                     {
    " A, H. G+ F( \6 F% t. Z
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);0 M& \1 z( f1 U  I% K2 W
  71.                     }
    2 Y5 _, _1 }) l% D
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息, k- ~/ `3 f+ Q, I
  73.                 }- i# @- W6 F2 p) K0 b: j2 M( s
  74.                 #endregion
    $ Q- k1 b  n. a: s- ?. B5 l0 b7 L
  75. " c- |+ b9 A) W) w! i8 _
  76.                 string descUser = string.Empty;//目的用户
    ! V5 Y. ]5 L5 x$ }) v! a$ m
  77.                 while (true)3 F+ _; Q& ~1 t$ }  {% ^$ Z9 B
  78.                 {) P# o! ?" V; P3 x
  79.                     if (socket.State == WebSocketState.Open)8 c+ K. h- T3 O
  80.                     {/ L. ~4 a% g7 v: r2 N7 a
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);8 @& y! z' e7 j( ?7 ?5 G6 c" b9 Y
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);" R" U: N7 f' e6 f$ w
  83. 1 I9 z4 r; z) B- a  U3 Q
  84.                         #region 消息处理(字符截取、消息转发)
    " K: j1 A2 S) V( j. J0 u6 Y
  85.                         try9 F( A/ L/ f3 ]# i; a/ t1 Y
  86.                         {0 R. y0 \" Z8 K/ E# J
  87.                             #region 关闭Socket处理,删除连接池  y9 P. @0 @) N5 G) ~" J) G
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    - m+ o8 E: \3 r9 G, z5 l
  89.                             {
    0 ^. O% {, E5 R, C
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池( l% k- x6 x5 C) G: G
  91.                                 break;
    , p0 Q  W7 e( K7 v; W, r* D0 M# m2 Q
  92.                             }1 l9 U  z2 G' o7 ]- B/ U
  93.                             #endregion
    * ?  O; R8 k, o# i: ^9 o+ D' P5 ~
  94. 8 e5 T1 w3 n$ R* r$ s0 O$ v
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息2 _; z" {" ]2 d4 a+ C) O6 U, E
  96.                             string[] msgList = userMsg.Split('|');
    1 T8 m: Y0 r# f- g
  97.                             if (msgList.Length == 2)
    , F( R% R, E5 L% ~# E
  98.                             {
    4 z2 }- l, f1 O! R2 @2 P2 X  B
  99.                                 if (msgList[0].Trim().Length > 0)
    & ~# c. w! H+ h1 R! [
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户4 J* C2 U6 K- U  `8 \$ |
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    . w  S+ G! p- i1 [
  102.                             }+ w, a9 t0 R" d* G7 ]4 v
  103.                             else' b. u$ r& r3 N/ K, O# I9 n) }) Q
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    , x+ \! t2 B" O- @0 K* t& n

  105. : }$ [' w' p4 y1 b8 Z5 d1 j
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线" n: u7 }$ @$ M0 Z* g7 ?
  107.                             {! ^: N6 L# @! i+ L# ~
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    ) @& K+ @( [, Q( N  w7 w. J$ U
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    : c4 X! o5 i' [7 A3 L& o2 {2 `
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);5 C* n( |- V" y9 p& U
  111.                             }
    ! W1 ?' \& ]  B* U
  112.                             else
    / W- t2 |7 v! P% t; h' i/ u
  113.                             {
    7 h, A, t5 A  L) ^3 ^. |" C0 T
  114.                                 Task.Run(() =>
    . J! F$ v$ d' X6 I
  115.                                 {
    7 \" }) ?! ]- f
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    " ?" ^% U4 h7 G! g8 ^
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    % X7 i8 n/ U3 r4 \" n; |* T
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    ( N$ i, Q! f& p& c
  119.                                 });
    , S; B0 k9 N, N; s; i! `6 w2 I! R
  120.                             }
    + P/ W3 G- d: t. v8 O" {' h
  121.                         }; o% z2 R* T* n6 h2 C
  122.                         catch (Exception exs)' ]5 R) Z$ H2 O7 q' _. T
  123.                         {
    4 q0 T1 w; E4 `9 D
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息' v, L/ W3 S3 {6 `" L& V4 G
  125.                         }& o6 n& S& }4 z, D
  126.                         #endregion
    # g% j  _& ]' t# |" m
  127.                     }
    8 O! M9 Q. T& N0 B, }8 f) v
  128.                     else/ G& L& }1 ]& A* U; n( ]
  129.                     {* A8 i/ G+ C6 G% s9 M2 C  ~& d0 X7 t
  130.                         break;
    % Y/ r1 b$ `  y% `- Q0 D* c: X. y
  131.                     }
    # |! I5 z& Z( U( M  Q
  132.                 }//while end
    ) b+ D6 x* P4 A5 \$ C0 N3 y6 @8 G
  133.             }
    * s- R- r+ p. c- F9 z+ z2 r, N
  134.             catch (Exception ex)
    . s6 v) A5 J& F$ v2 l5 ]/ i6 x
  135.             {8 d' d- [  v$ @4 r0 e: \' i
  136.                 //整体异常处理  F" |- j8 v& O2 D# A
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);4 y0 }* h' U3 J1 w) o
  138.             }
    . Y; B$ g- k! B: }' J
  139.         }; C. I2 h7 K, L" P
  140. % G# S; K& [2 \" P, x; U1 y) `

  141. 7 _) e  a5 `7 s4 u9 x: f8 c/ P: k
  142.         public bool IsReusable
    # m1 b, h) H9 f8 M: G9 |4 W
  143.         {
    # c. F/ \% r/ e4 i: ?; }" X
  144.             get2 |* c3 X7 P# e% h' a( U7 W- C
  145.             {" }  T0 J: G- r% a
  146.                 return false;2 K& V1 J# R. V- c
  147.             }. i$ }5 [6 E4 y! ], a: l
  148.         }
    * \! f' V/ ^+ }, p/ K3 f
  149.     }
    0 I: Z" v; l- N) L  t
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

) O8 J; ]- R& u0 s! s- R9 w
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-6-19 22:39 , Processed in 0.058009 second(s), 22 queries .

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