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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
0 |; T( Z8 f# B! @
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    , O. n* A3 k! D3 C6 n' Y) p1 y
  2. using System.Collections.Generic;
    , K% H/ t$ v8 I3 V4 z' S/ a) \1 b+ {
  3. using System.Linq;8 N. G2 o4 x# U& V( W. u
  4. using System.Net.WebSockets;
    & Z, x4 _3 v& d: o3 L# O) b
  5. using System.Text;5 w/ l8 K. L, o1 {3 m# }! d
  6. using System.Threading;- r8 O% K, W; ~4 O8 S/ ^
  7. using System.Threading.Tasks;- o+ }) ~( p7 j8 c
  8. using System.Web;
    6 v8 U: T' K) E/ @! b, |/ m
  9. using System.Web.WebSockets;0 ^& g9 R7 N) i, s# {
  10. $ {+ T( T2 B4 h( o; O9 f

  11. : [/ q- c* D( q! D% v  z- A
  12. namespace WebApplicationWebsocketHandler
    / Y4 A( y* H3 D5 M1 B
  13. {" h& \: _8 A4 d. M8 N$ U# D, z
  14.     /// <summary>
    2 H; v# }2 S. f9 F; z- a
  15.     /// 离线消息& ~8 j# {* ]8 V9 d
  16.     /// </summary>
    2 h+ p* e3 P/ J! M: Y
  17.     public class MessageInfo) Y: v2 C5 }4 h8 X9 _9 @
  18.     {- |1 B; H* `8 I
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)' Y+ v5 ~5 @" x
  20.         {5 N- ^0 b" f3 k0 y* i
  21.             MsgTime = _MsgTime;7 c9 s& W6 q" r  B5 O
  22.             MsgContent = _MsgContent;
    , q9 X1 L) h1 q
  23.         }
    8 l! _" @- t/ r  Q/ m, J
  24.         public DateTime MsgTime { get; set; }
    # A1 l- E) A7 c' j! _
  25.         public ArraySegment<byte> MsgContent { get; set; }* ?8 @. F' ]2 e; J# F2 I
  26.     }' j0 X  P9 w% V, Q
  27. ! Z' K* w+ ]8 s# w2 ^/ \/ e5 ?; s

  28. % d# Z- q$ e* O; K

  29. 3 w2 o5 I6 ?! W
  30. ' Y9 j" |# ]% t; z: |3 h
  31.     /// <summary>
    % N# b' r! z- L2 d
  32.     /// Handler1 的摘要说明% w& G! U& g4 V1 {
  33.     /// </summary>
    0 M/ L8 S( _, Q  I
  34.     public class Handler1 : IHttpHandler
    - i# @3 O8 S0 N" d0 a0 Q1 ^. A
  35.     {- P4 `6 C6 W0 ~0 [9 ~
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    ( Y1 a3 R% O/ o- v: i
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    , f8 j5 y: e# _! w) C4 x; p
  38.         public void ProcessRequest(HttpContext context)" S- T4 P3 X6 {# h8 e
  39.         {* d0 w: T" p& Z  f8 f* l
  40.             //context.Response.ContentType = "text/plain";
    * ~/ a; r/ X- I( d9 P. e. e
  41.             //context.Response.Write("Hello World");0 m7 l7 X1 [% p( }/ p5 K
  42.             if (context.IsWebSocketRequest)
      T1 ?- X9 u3 }+ Q
  43.             {
    . J/ \# {1 e4 v$ m$ m# F
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    ! g9 G" }( n* {% t$ C
  45.             }
    , I. P$ l  G+ b
  46.         }
    5 `, x( A6 m! ?- ?4 p0 r2 {

  47. + u! F, b2 S/ K( k* A1 `& a& J
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    9 f7 c0 `; X, r9 v( @
  49.         {
    * u0 K8 R) e# l0 B
  50.             WebSocket socket = context.WebSocket;9 J4 c8 B$ d/ h9 t- a' h% q
  51.             string user = context.QueryString["user"].ToString();
    : S1 l; t5 s3 F8 a" F

  52. # r, {- F& O+ f0 W
  53.             try
    * y9 I6 ?3 R9 v+ K2 N) G& C5 I+ _' d
  54.             {6 o$ m. l' J+ Q$ z. Z4 d3 D9 {
  55.                 #region 用户添加连接池& l* ?4 H$ M! |( a! s6 D% `6 p# M
  56.                 //第一次open时,添加到连接池中# b( K  [9 A  `
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    " v* L- g4 j' w7 Q+ w9 g: C+ X  I
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加* }  y" t' v+ K5 f8 k# K: `
  59.                 else, m# G! m! b) q- g
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    ; Q! t; r  N# e' Y
  61.                         CONNECT_POOL[user] = socket;
    3 |8 j/ H" W. o3 S) Q8 N
  62.                 #endregion' f$ Z: b6 m7 B+ n5 F$ ?$ m! `

  63. ' H4 c1 M, T/ x( k: G' [- ^
  64.                 #region 离线消息处理1 `. a/ X5 {7 t: w& D. w8 g" e
  65.                 if (MESSAGE_POOL.ContainsKey(user))/ Q1 S0 F2 q. l( ?0 h
  66.                 {
    ! O0 X1 e6 g; z0 U( D- P/ p
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    9 [  M' X3 u/ h' G
  68.                     foreach (MessageInfo item in msgs)( ^- F% Z+ \6 I' K. a
  69.                     {
    5 D0 }. d4 w! z; x9 S) h/ e; ?, S
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    , [$ X9 C' Y4 F/ G% |
  71.                     }* ]. T' t/ n' E
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    # U$ k  O' P0 B# J. I
  73.                 }/ V" `* _2 K7 t: z3 j$ K6 o
  74.                 #endregion9 }. ^( v8 {! R" @7 U1 c; R

  75. 7 z* [/ _8 @# g1 V. A; p% d
  76.                 string descUser = string.Empty;//目的用户) p1 x9 u6 n) \/ H2 W0 \
  77.                 while (true)+ ^3 _  x1 }" ?1 y7 Z
  78.                 {
    4 {. `$ Z+ q. f, c  b) E; i4 h) |
  79.                     if (socket.State == WebSocketState.Open)( U% u. y8 y4 k% c6 Y, m
  80.                     {
    ( J0 C. k( K( g- ]; F+ Y# e
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);/ l! S% O3 L. Q) y4 k* ?' C
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);$ F4 B+ B' G! a+ u$ Y- L
  83. + [& D" F' B5 L. H/ y7 W- x0 H3 L
  84.                         #region 消息处理(字符截取、消息转发)' f# o' j' X+ R* Z0 U: w+ c
  85.                         try
    ' Y8 M3 h; O# B- g6 k
  86.                         {
    & L& u8 y$ Z: x7 ~8 Y* S
  87.                             #region 关闭Socket处理,删除连接池: J+ G: v, n3 Y; \& Q; |
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    2 E8 h$ \5 p& U5 U7 v: Z% R/ g. o
  89.                             {* y, ]) `2 K# z7 t5 k
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    + W% P/ j* @0 N, Q
  91.                                 break;
    5 b! O% z- ~$ Q% e% m% z
  92.                             }' l. h/ O& l8 a3 }2 \9 m% j
  93.                             #endregion4 C, l& N; S/ X! {: y

  94. 3 i( z. t* s/ D# D4 m" d+ L! e
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息' x5 v2 f, j1 O
  96.                             string[] msgList = userMsg.Split('|');4 {' e6 E% {' G7 g' Q' |
  97.                             if (msgList.Length == 2)
    ' j( P5 g2 k  [  q9 t& I9 W
  98.                             {
    4 m) N5 l9 S& t4 i  P
  99.                                 if (msgList[0].Trim().Length > 0)) M, M- O# G/ K, Q
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户& `" T, o& m$ H! y) X1 Y
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    ; g9 k/ A' v9 i2 ]
  102.                             }
    ( x/ o6 S" B" b7 f
  103.                             else& ^0 S: i2 E. e6 e8 ]; Z. z
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));2 E+ o- ?4 |$ \& u
  105. 5 x  F$ f) E4 k
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    - P+ H* o; ]: [
  107.                             {' S* G: \/ n% Z, U1 ?, e' \
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端0 m7 x1 m7 c! Q( j- ^0 W% R
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    ! n# l+ T5 E1 Z2 x8 i$ S
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    0 Z. y* q& s" T1 Y( D
  111.                             }5 @+ d( z0 w( e. R/ I: ?: J
  112.                             else
    # a1 w# r) w& \+ j) ?
  113.                             {* u; E7 Z8 j2 M0 r
  114.                                 Task.Run(() =>* V( z$ p! k# g: q. u) L5 G7 S% J
  115.                                 {  G# x( I) t! U- x9 x
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    4 l% g/ G  ~! J3 o! }
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    7 {! x( t6 v/ C. N& n
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息$ T7 n/ g- \- ]; d% c
  119.                                 });
    $ \' E+ O  ~4 r9 ]
  120.                             }0 J- W( O" h) ?! t
  121.                         }& g# K3 P! P! J; `
  122.                         catch (Exception exs): n, s2 k$ @9 s! q% K
  123.                         {
    $ d4 n: ]/ G, [; @% S0 E& c8 w
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    $ [7 h: @+ D6 j7 F
  125.                         }% A4 a' e# T7 |3 D7 D" d1 V; C" Y
  126.                         #endregion5 [3 _6 Y3 n6 q6 O$ g
  127.                     }4 Y" {- O! r! ^8 |  ?# @/ `
  128.                     else
    ! f, H# @. W* M8 v% V+ g# Q
  129.                     {6 w" p" f5 y, ^* t5 S5 j
  130.                         break;
    7 o9 ~9 o" w3 n$ y9 o
  131.                     }* h& K1 M$ V$ |
  132.                 }//while end$ i- J5 a6 [$ H
  133.             }9 F4 b( J- j5 ]0 V/ ~2 q
  134.             catch (Exception ex): u$ ^% z: k1 ^0 Q/ Q3 r* @
  135.             {
    1 f1 s' b6 c# b% a, ~9 Y
  136.                 //整体异常处理
    , s* j. Y% y9 v( }# p4 i$ y/ ?, G
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);0 Y3 l) W3 Z. u0 ?# T+ j
  138.             }
    : j. ]  N5 J0 \, f
  139.         }
    : g6 d$ N# V; O- Y0 ?0 S. U

  140. 2 U; {3 U( P9 ?2 O5 d
  141. 1 [* v4 O8 b/ s9 x5 y, t6 I
  142.         public bool IsReusable  k) `# D' [# T6 _
  143.         {$ q0 @$ l, e" v0 J; k" N5 ^
  144.             get" w4 g  ^1 y! Z: b' ~
  145.             {
    " c1 O) A& I% q. P8 G9 D
  146.                 return false;
    / f  i! ^6 n8 A& e% G) G) d
  147.             }$ ^, i$ [  F9 x9 @! u& K2 z' [/ D
  148.         }
    # P! O" {' w3 q8 L; n& `
  149.     }( D# {. ^. G0 i+ r* T4 F
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

  r4 g! [* E) c4 E
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-10 03:13 , Processed in 0.139496 second(s), 24 queries .

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