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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

* {- u/ f4 w! U
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    + g  K* x: n$ R& o7 X1 a4 H
  2. using System.Collections.Generic;
    % {6 B& M- ?+ w8 x+ _  e) W3 h3 t2 D( D
  3. using System.Linq;3 M1 u" x: k3 \- q" `
  4. using System.Net.WebSockets;3 p4 O9 @* r8 I: F
  5. using System.Text;7 L) @2 I; b& p: _% g1 Q5 A! i; o
  6. using System.Threading;
    8 B+ H+ j& V0 `. w; X& B% p, Y
  7. using System.Threading.Tasks;/ n0 Y( o! d  S% r* g# g3 ]1 J
  8. using System.Web;+ t2 {  F& v- J* J- h- ^
  9. using System.Web.WebSockets;' O1 U, b6 C( l, U4 k
  10. + T" B- G3 l: n0 ?) y6 b
  11. % Y# a* Z" F6 U' D  i
  12. namespace WebApplicationWebsocketHandler
    . i. _/ y" e. g6 G) z3 o+ Y! O
  13. {
    : C2 t3 R+ ]1 s
  14.     /// <summary>
    / b4 r# i  `$ v% z- r3 v, i- d6 N
  15.     /// 离线消息
    ! j" Z# J) K  G8 a
  16.     /// </summary>
    . X- g$ N$ j& u/ a. A) n9 W6 [8 R; ~
  17.     public class MessageInfo" s6 Q0 ?; s; |/ y! [2 G7 B
  18.     {! _; [% i* |- T
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)$ r# a8 {) V  B
  20.         {- p% z2 q* n) K0 g! P
  21.             MsgTime = _MsgTime;$ W7 _5 T7 C5 L) M- Q
  22.             MsgContent = _MsgContent;: i3 J2 M" C5 h
  23.         }8 e- e. i+ M) ~+ \! Y9 W
  24.         public DateTime MsgTime { get; set; }
    ! _% U) y8 R% @
  25.         public ArraySegment<byte> MsgContent { get; set; }
    3 |( f3 ~& i+ N; k" b
  26.     }' r1 ]; B- l/ B5 n5 {: n6 |

  27. 3 z- f" o" M, m! t- Y& J$ L

  28. / ^9 _( ~7 O! J0 X; e
  29. 3 y+ p8 a6 c9 E9 }; t
  30. 4 V4 j+ s! N. V# Q4 K. i3 Y
  31.     /// <summary>
    0 _8 F* f7 ~% T! Y
  32.     /// Handler1 的摘要说明7 I" v& z: ?+ W; _! i, s
  33.     /// </summary>3 U2 A* f6 R; ~  f3 l
  34.     public class Handler1 : IHttpHandler
    " e9 F- O3 ~: M/ ?: Z0 h- v9 a
  35.     {" J1 C$ R* a4 m* h; k8 ]2 _- }6 U
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池2 `  {- r6 e$ S" ], o) ~- @! X
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池% a# P- Q4 B% |  J
  38.         public void ProcessRequest(HttpContext context)# C; A) z( X2 P+ X8 b- V
  39.         {
    6 a* y8 ^' E$ h# |# x) J
  40.             //context.Response.ContentType = "text/plain";
    0 [1 I6 t! z* ]$ k# ~' B0 B8 o
  41.             //context.Response.Write("Hello World");' t/ Y% I8 r4 i, @, l. P
  42.             if (context.IsWebSocketRequest)
    3 C2 Y! K, ?6 e$ V& c" L+ M3 P
  43.             {
    % |2 D# m/ I3 S- y0 ?
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    9 W# i; U8 B5 K/ N+ b
  45.             } " p  U+ H( k) C2 d4 [
  46.         }7 e5 G( B9 n5 P; c0 Z

  47. + H) i9 W+ R8 I
  48.         private async Task ProcessChat(AspNetWebSocketContext context)) b4 s' X8 o% l5 ^
  49.         {3 J& o4 A7 a4 M# ^: g- E! T
  50.             WebSocket socket = context.WebSocket;* S  b2 \' a3 _, X
  51.             string user = context.QueryString["user"].ToString();$ [6 A8 W; z* |# r/ r( D5 H4 E- N
  52. ( ~& ^& c$ p! M
  53.             try2 H+ S% T  @) A  y" h
  54.             {
    ) T7 N2 {; g- |2 `7 ~. S) t
  55.                 #region 用户添加连接池
    2 n7 f2 ]8 v% M* e; \+ S
  56.                 //第一次open时,添加到连接池中
    1 o$ v3 d. B+ |! J1 U2 A
  57.                 if (!CONNECT_POOL.ContainsKey(user))' s- g# U" c+ h; z4 _7 ^
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加& j+ i9 j! t2 {2 h, _
  59.                 else
    ! X+ ^9 F% U& v. ]
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    ) l& J4 c, O7 @6 Z1 H# }+ X
  61.                         CONNECT_POOL[user] = socket;
    % s  ]3 l- z" K! @
  62.                 #endregion
    8 |  n. u+ t1 Q3 A5 J% v$ S

  63. 5 T7 l( P: l! j7 k' p- g
  64.                 #region 离线消息处理' ]8 X: _" W( ^& b
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    / p) J7 v1 }0 c6 D
  66.                 {
    / E, M5 ]0 R/ u4 n) g
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];4 x3 Q  f2 C0 S7 A
  68.                     foreach (MessageInfo item in msgs)% v2 C( Y) L0 f( |/ [8 T1 ?
  69.                     {! V& C! h6 g/ \% q( H% G: n
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    : F, v$ |! C' K* g
  71.                     }
    4 i* R: u* t/ z& |9 b' g; ~
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    ) v$ d# B5 V; Z0 h! A
  73.                 }2 w0 p& I  m* V  l; I' V
  74.                 #endregion4 i8 a; |. S' |2 o5 z9 v4 G

  75. * _; p9 q9 K1 K) H) j; q  S/ I
  76.                 string descUser = string.Empty;//目的用户
    6 V" t1 \: C0 @$ v- a
  77.                 while (true)
    ! x* n/ Q) n9 o8 L* e: L
  78.                 {1 h, D( u/ u1 Q, u$ f* Z  _
  79.                     if (socket.State == WebSocketState.Open)
    ; Z5 ~8 a4 d- ]* Z  c! |
  80.                     {4 L6 _% w/ P9 h# y$ o/ @& [2 I
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);5 W; Z5 o$ O1 G9 M
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);1 a9 r- y  l' L; \# t- D# s/ j, @2 K

  83. ; S3 J4 Q  c, Z9 j
  84.                         #region 消息处理(字符截取、消息转发)
    ' h  ^* G: b, r
  85.                         try: t) g6 n6 z( y( t7 e5 @
  86.                         {% h: s# N% w& @. P( n
  87.                             #region 关闭Socket处理,删除连接池
    7 g2 F$ H7 G- [9 Z( r9 ?6 h  p# Q+ n* v
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    ; B& E* y0 Y, b$ g
  89.                             {. [$ v2 S& X3 f+ n$ g9 ?
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    ( Q0 T( L7 G0 {4 H# O  P
  91.                                 break;; R! a# K$ Z% P( m& L1 I/ f' h
  92.                             }/ P7 u' g/ Q6 f, N' l- Z3 I
  93.                             #endregion2 _0 }8 D  e, ^

  94. " S1 |' L- C& f: d" A% S  J
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    & g. W. i0 \$ B. i5 f8 a
  96.                             string[] msgList = userMsg.Split('|');
      e- z. d4 g8 Y1 \9 J' b
  97.                             if (msgList.Length == 2)
    $ _; K, e- Z( A$ |5 w9 F5 K: \6 e" L4 t
  98.                             {# c$ ]" ]+ {- C! a
  99.                                 if (msgList[0].Trim().Length > 0)4 v; P1 }8 D3 l3 L  {4 F
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    , f; O8 Y; g' Y- }% m# c1 w$ c
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    2 v+ w' D/ a( d2 t1 c1 c
  102.                             }& i+ [4 C: u! z3 i+ G  x5 W5 N
  103.                             else0 |# u. n4 [1 J3 x
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));. @$ Z. U4 X% W
  105. , T; p8 D) R) F6 t) H" e
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    ; |. E1 s# s3 i' N. y
  107.                             {4 N! L. W3 k0 Z; i% u4 n6 a  X
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    7 x6 A9 d. ~1 J, a; b/ O$ Q
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    8 `5 K3 ]! [9 q9 |, G: @! M9 @
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);4 h3 `3 ]2 F. ?' D/ D! V+ K7 k+ _! l
  111.                             }
    % J6 v  _# m7 ^% s  g" Z5 R
  112.                             else0 g1 i( a+ q5 j5 P6 n& X
  113.                             {. ?& v/ I, M! G3 ^8 w. d9 s
  114.                                 Task.Run(() =>
    ; U& F1 B2 u* p/ v* b
  115.                                 {
    9 r* `. i! C( J9 H% h6 S
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中3 s& T) @9 H6 ]" w8 D# I
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    9 ]5 \; U/ t+ b) c0 a0 W: W
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息% R$ E4 }+ w7 i$ K: q
  119.                                 });
    3 o- j3 i0 z  F: H* A! m
  120.                             }" b# x7 _+ ]: F  p- O' b
  121.                         }) ~# t) ]; x: P* W! ~0 i
  122.                         catch (Exception exs)
    0 t# \! Z" `0 Q5 S  v
  123.                         {/ b/ V0 Z( I1 _. ~0 g* V* s7 L
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息' S  B: o& c% [4 O( C; @2 w2 u
  125.                         }
    - X' x2 O. e$ C) {, @% @7 [5 J1 @
  126.                         #endregion" B' g. z1 F5 X
  127.                     }$ r" P; T, U% y5 }# [# Q
  128.                     else
    # o: [6 M5 r  @2 ^/ f/ w
  129.                     {
    $ F9 A* L! e( u9 V  k9 b
  130.                         break;2 f0 l7 y9 _9 p8 y9 u# C5 M% K- b  e
  131.                     }! r/ g1 ^  h  A1 f4 D
  132.                 }//while end
    # K. K9 @! y. g  v$ L$ Z9 X& V* F
  133.             }
    : p0 I4 C! h( Q' Q
  134.             catch (Exception ex)
    # S* z* j8 q) Y5 q5 Y) z9 \  Z
  135.             {% t: o9 b- B' d+ L: R0 w- g& r
  136.                 //整体异常处理
    ! `/ W/ W- E6 m) o- d* U* h9 G
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);- x& G$ Z* }/ T9 i" P' C. J
  138.             }
    * w; T( e( I4 t. A
  139.         }4 P- w  x* I% ]
  140. 9 ~: i5 j- `3 i" h

  141. % v7 Y# w5 P1 h1 f8 x5 i
  142.         public bool IsReusable
    * t: @" H' p" ~
  143.         {
    0 s- Y5 t; }  B3 T& }8 L
  144.             get, T5 R" E. F2 ?/ w, e/ |
  145.             {
    9 U, S( u3 s0 C' U* g4 e. z
  146.                 return false;
    0 q% }; S6 K6 I( D* ]9 W. Y- j5 R
  147.             }0 E8 |9 h* r( u  T
  148.         }
    ; d" t0 D( q' `7 w( p& j
  149.     }
    0 p& a- l* P( K8 H. c
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
& X3 z  V! Q3 T" D5 H
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-17 17:14 , Processed in 0.141154 second(s), 24 queries .

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