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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
+ H9 ^' \$ t8 w
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;# E' M. o2 G& t7 y. Z5 k9 R/ }
  2. using System.Collections.Generic;% ?5 |" V" z- ?) U( S- c; y3 W  S
  3. using System.Linq;
    ) ?. |2 P: f5 s
  4. using System.Net.WebSockets;
    * s& m  ]/ V4 M3 M* \. F
  5. using System.Text;6 m! K& F" l, t" M& T
  6. using System.Threading;2 c; _6 B! |: M( f- g
  7. using System.Threading.Tasks;0 T: i$ e, |! ?6 P7 F
  8. using System.Web;
    . l2 T; j0 v7 T. O1 k
  9. using System.Web.WebSockets;
    4 s4 n% s4 v1 U9 ~* Z- ]
  10. 8 [4 c* o* o. ^! \! ?5 U( z: k4 @

  11. % M, u* b. \  g6 C" |
  12. namespace WebApplicationWebsocketHandler* v/ s0 K" q& I, o; o) u
  13. {4 C; z. I. [" z# m2 `) Y2 C6 y# t+ F
  14.     /// <summary>
    ! F4 ~& q5 `+ K6 K, f( ]2 n# _
  15.     /// 离线消息
    6 [9 Q: v& U4 t- O/ J
  16.     /// </summary>
    7 V& l$ Y6 e. U) A( Q! b( B
  17.     public class MessageInfo
    1 R  ]- m+ N$ H4 g& H4 l& G
  18.     {
    & j4 U8 S% H' n0 u" _1 X7 `4 L: E" o
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)" Y  w6 T8 e, T  w3 X9 A. |
  20.         {8 H' M3 P* k7 b: e( k4 |8 w
  21.             MsgTime = _MsgTime;
    * j. w& p4 u3 q
  22.             MsgContent = _MsgContent;3 O! X$ X' e8 u2 |( N/ _+ n1 `
  23.         }
    0 E( u2 G: B6 t9 G
  24.         public DateTime MsgTime { get; set; }
    # F+ z2 V6 a$ [% T4 `* y
  25.         public ArraySegment<byte> MsgContent { get; set; }
    ( F. L  b5 c, I3 [* ^7 Y' g
  26.     }2 ~9 q) K$ ^: k3 g

  27. : p+ l( ]5 q' [2 g6 ?2 m" v! d

  28. : a, u, r% r. c* F
  29. & M/ Z! Z! j: j( P" J
  30. : d0 ?( ~! Z7 J+ h' T% T0 Z! B, m
  31.     /// <summary>! ^4 k, j0 l. c
  32.     /// Handler1 的摘要说明
    . b2 D" Y# t- Z3 w0 E$ j
  33.     /// </summary>: L( ?* v, X# s' k4 S! f
  34.     public class Handler1 : IHttpHandler& ?1 |" b- B& w' ~" e' E& e8 K
  35.     {- ~4 V" }9 `% I( ^- x# ^9 {
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池) Z5 R, I" m3 l2 b, Z# u6 m
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池5 F' ?6 j& s9 s: R# O& N9 D/ n
  38.         public void ProcessRequest(HttpContext context)" @" x2 e  X" X! w
  39.         {
    - ~$ H) n* r9 O, T1 b! X
  40.             //context.Response.ContentType = "text/plain";
    ' K+ m' m7 B/ d
  41.             //context.Response.Write("Hello World");- F; T2 Z* [- f+ b* G  y2 V
  42.             if (context.IsWebSocketRequest)
    ( p' r  T- Z( l- ?" p
  43.             {- k+ V2 B0 q# V# X
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    . C: z8 D4 F' F5 V9 }; \- U9 }/ ~
  45.             }
    4 Z0 Y+ f; |5 N: j$ @9 w% ?
  46.         }; D5 L- k9 n! A' t0 m/ N$ d" {; @  f0 Z
  47. + U4 ^* ]; v3 i$ J) j
  48.         private async Task ProcessChat(AspNetWebSocketContext context)7 G, v! @( e, E5 C8 J0 s, r
  49.         {% P5 F: A" @! I: |
  50.             WebSocket socket = context.WebSocket;
    2 _/ j" Q3 @6 q( K" N3 a5 n
  51.             string user = context.QueryString["user"].ToString();
    / o/ p) {4 k" A4 D$ T. {
  52. - k) w. L* k. t) r( o) o
  53.             try8 W9 E. h' C) {/ Y7 [/ G
  54.             {8 Z1 H1 K/ T. d2 h5 D6 w! v
  55.                 #region 用户添加连接池2 z6 F. K1 q) ?: a) x" W7 k, c6 r7 r
  56.                 //第一次open时,添加到连接池中, l% q6 J) n6 A9 ~7 L1 I+ L
  57.                 if (!CONNECT_POOL.ContainsKey(user))5 `5 s# R2 v  {2 Q; }
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加# ~4 E% A5 N! j4 X) a
  59.                 else. |* w3 s2 d/ @6 y, }/ I
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    & q4 J" s- H# e0 s6 ]
  61.                         CONNECT_POOL[user] = socket;
    + P4 u# j% C* c: L, L
  62.                 #endregion
    ( a5 L( h) w% j# k- B. L) R  F
  63. 9 L5 M% ^7 ]% p, s& A  O
  64.                 #region 离线消息处理
    & r- s1 ~9 _) ]1 B& \
  65.                 if (MESSAGE_POOL.ContainsKey(user))) s0 I* G% U- g! s7 G
  66.                 {
    : o1 B9 q) C1 K4 U
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];7 S" j2 S" {  C' x" n( b" x+ s: `
  68.                     foreach (MessageInfo item in msgs); [' P0 W* t/ p6 ^
  69.                     {+ x, S! T! h' d2 X! O  e
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    " e9 \& f8 V4 {5 i+ s0 F+ ?# G) j4 C( Z
  71.                     }
    2 S, X" O9 d+ D, h6 n4 {& ]
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息' ]! t2 I! n* Y  T4 A
  73.                 }3 N; x" q  }& C8 E
  74.                 #endregion
    4 q4 F' K: J; _8 K8 U" ~5 m

  75. : w. C" p2 Y$ z' K  Z) F
  76.                 string descUser = string.Empty;//目的用户
    " h' [# |0 Q: l5 A
  77.                 while (true)
    , M! g$ K1 t" B3 |
  78.                 {
    ( a5 e' I9 S& D- V/ s% d+ I
  79.                     if (socket.State == WebSocketState.Open)
    $ ^, X$ R1 N3 g4 q+ n: Y
  80.                     {
    ) |1 W. y3 N. y8 |
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);2 Z2 Y$ Z% x7 A0 t+ B
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);+ B% k+ M7 h8 u; o

  83. - n# X( P2 |9 S$ s! v
  84.                         #region 消息处理(字符截取、消息转发)2 R! b# J7 P8 G
  85.                         try
    2 G0 b  N% R0 D. P6 D4 b
  86.                         {
    8 C% ]! a, q/ n5 E" @2 X* q
  87.                             #region 关闭Socket处理,删除连接池+ p5 G- }& r5 u. W  H
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    $ X; `; K" H" G( ?! Z. z
  89.                             {
      J3 q. Z4 k( E0 z" r6 d
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池6 A7 _7 G8 A6 j$ T2 h
  91.                                 break;
    : T- i+ A/ g  [& z
  92.                             }) |, s5 t; u0 |/ A; M6 j; M
  93.                             #endregion" x+ ]# o5 }9 N- R
  94. & P: q1 v$ U2 w; {- S
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    ; a. D0 ~9 }! n+ }& n' [* q( K( C
  96.                             string[] msgList = userMsg.Split('|');
    0 o+ F1 B  |2 h
  97.                             if (msgList.Length == 2)* x1 V2 p( s, L, k* C- S) D, j
  98.                             {
    5 s/ h! L8 M0 L' S3 _# v* {. B
  99.                                 if (msgList[0].Trim().Length > 0)' i' P1 k" C( }. [( z/ M/ N; r1 h9 s
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    $ E: I" o1 A) U; f, ]
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    & v, W$ N% f+ b3 Z& ^
  102.                             }) ~; F+ P8 S8 Q% ?  @3 ]7 n7 x5 m
  103.                             else) n0 E: F6 I, A. Y& c4 ?# P: Z% g
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    3 Z5 }" w" |3 k& N0 i' P  f
  105. 7 H' l' z8 \! A' f( \! g; {+ X( K
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    $ P) n: q* t2 i* G! Z
  107.                             {4 x4 l0 ?  n4 U6 L0 l
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端! e& z  ?; G: ]* z* w9 i
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)2 n% c/ G1 |: F/ h7 E. C" {
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    . }& |6 \9 j; ~- C7 {4 t
  111.                             }
    ! ?! T& o; E% v
  112.                             else
    8 J. a+ [8 t! ~0 E) e) l# m9 K
  113.                             {
    + X3 j4 r$ ]' _8 `
  114.                                 Task.Run(() =>
    5 S( O8 U+ {& @: X# {; B
  115.                                 {
    * p/ Q7 m4 K7 R8 P0 x
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    : J/ J# h5 T: e
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());3 ~- Y2 A/ @* _: h) x
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    2 S& l5 e) Q+ h" t7 z1 {% R
  119.                                 });
    " I5 j. e5 p! d9 ?" v. F" p
  120.                             }, z  A6 m& N& Q9 Q. v$ i$ I( k" H( z
  121.                         }
    ; e7 ~* o& ], O( S" y% y% g
  122.                         catch (Exception exs)) i" Y6 R; e2 f8 l8 o* F& r  h5 D
  123.                         {
    : p! @5 l& b' ~0 g0 h: t
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    ' n: f+ W4 g2 n, N
  125.                         }& ~1 X! C4 @' c9 m6 A) a
  126.                         #endregion
    & X& c$ I/ @) P' q; {
  127.                     }/ `! W2 a: o* \5 P* P6 c8 X
  128.                     else
    1 k8 P) p% e. M% l0 G
  129.                     {
    * D: A5 v% t4 y* X1 B. ]
  130.                         break;% R% e6 _9 N3 r! {% ^" B
  131.                     }
    7 m& P; s: a: J8 K3 {' `4 @
  132.                 }//while end
    * y9 f' V0 N0 L- R( Z( T8 m
  133.             }
    2 i; p3 [6 L* q/ Y: ?# R
  134.             catch (Exception ex)
    ( R8 a6 P! _8 ~9 O3 Q; M9 G9 Z/ a
  135.             {
    ; _! a  X( K7 K8 e( H
  136.                 //整体异常处理
    + h) M/ ~7 r9 b6 [5 A. t
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    ( X5 l% ^: L  d7 ?
  138.             }0 a6 ^; J+ A) b+ j; I( n, G
  139.         }
    & u  C' I9 N( B$ d+ Q0 _

  140. $ {: u* z" U4 P! \

  141. 1 ]( _: q* q$ s/ Z% z
  142.         public bool IsReusable3 A: u! t8 i# h
  143.         {
      a4 g% W! T6 S& f$ {, l
  144.             get6 [5 b. `2 L9 ]7 _* Q1 ^
  145.             {
    * l3 _/ E! {, A  E; o: [1 W* Q
  146.                 return false;
    9 N; \9 u4 U: ^& ~
  147.             }3 R, |9 ]$ t- U
  148.         }! F7 k7 t( L: b( Q) T- D1 V
  149.     }
    : l% M6 h  s( G! n* f  U4 \1 t/ p' W
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
! q' Y8 Y! T' g5 p$ X) J
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-17 18:32 , Processed in 0.117845 second(s), 22 queries .

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