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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

- G' f) W  H# R
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;: R" ]$ W; t5 W+ p6 g$ f) p3 a" y
  2. using System.Collections.Generic;
    ( R7 `# ?8 V8 S; o6 ?
  3. using System.Linq;+ M! y: p7 d% C, p* z" d
  4. using System.Net.WebSockets;
    3 W, R/ O$ H2 u9 d; n
  5. using System.Text;) j" Y8 I0 Z7 O% M4 u9 I4 }
  6. using System.Threading;: R! G0 P/ m1 _" G- j/ p5 P  U
  7. using System.Threading.Tasks;
    ; a$ L- B" N. N* t: o3 W; N
  8. using System.Web;$ F0 \& r$ ~; i0 I. ]
  9. using System.Web.WebSockets;
    - i. |" q5 ^' ?( F3 L, Q! G
  10. * A* [- I" o, j7 o

  11. 7 x- `# w% A/ S2 O
  12. namespace WebApplicationWebsocketHandler
    " `* ~* C" c1 X3 ^
  13. {
    . y# w8 l3 L0 O
  14.     /// <summary>: W' @7 c, g! Q% d; k& h0 |+ \1 ]. l
  15.     /// 离线消息; l! u  `- G4 g7 H3 u3 G; B3 y; U! r
  16.     /// </summary>2 J. }, V3 k) J# J' h8 C% J2 s8 N
  17.     public class MessageInfo
    1 `, m( r' b4 @6 S3 B
  18.     {$ ^+ W0 I0 u' v
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    2 P5 |9 e5 p# g: {2 |6 M/ V" X
  20.         {# W5 ?  G  [. Z9 ~$ ^
  21.             MsgTime = _MsgTime;
    4 n8 B$ t/ q8 A+ g) u
  22.             MsgContent = _MsgContent;
    ! p  T5 \+ g; y, ~& O
  23.         }
    . ^. S* ^  s5 `. `6 B0 ~  }
  24.         public DateTime MsgTime { get; set; }. R8 A) b% R, L, G: u% ?
  25.         public ArraySegment<byte> MsgContent { get; set; }
    8 ]) P( L+ j! s" _
  26.     }4 N2 _- z9 T$ |! t, Y
  27. & M: Z# `5 v& P# F: O  a
  28. & o, M, {. D, ~( e0 c3 {
  29. & E4 z0 W1 b5 M; A3 f) |
  30. : O( W  G) m5 _( O/ p- T
  31.     /// <summary>; o/ N8 Q& X1 C7 j' b3 O
  32.     /// Handler1 的摘要说明
    5 z4 \( _! i, v
  33.     /// </summary>
    ; [6 z. `9 L) |( F2 i0 t+ `
  34.     public class Handler1 : IHttpHandler5 D& C' F  C" x- g8 l) H
  35.     {. a* p  s% p5 f) n! P9 x# X- [5 D
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池2 T3 [) d7 K5 W2 w* P: \/ w2 k
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池  C% H# v6 W, i  s' _
  38.         public void ProcessRequest(HttpContext context)0 J8 X. _# B' F9 f: M7 ^! S/ \. K
  39.         {! W# L' v2 w, |  j
  40.             //context.Response.ContentType = "text/plain";
    0 x) S- c! S; u! \2 b% |6 W4 a5 B
  41.             //context.Response.Write("Hello World");
    # q- C8 g1 p- T  q( H6 C
  42.             if (context.IsWebSocketRequest)/ f' P* T- b+ f
  43.             {. r+ Q2 [! u& a$ g
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    7 V3 f$ P3 I) `! _0 h
  45.             }
    3 S& `! {9 y) i* \" j, `2 _3 P1 h
  46.         }0 W; N+ g* T  s" y4 p; |

  47. : G8 Y2 T% ~7 l6 G7 f
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    & a& d1 @4 N4 Q" n+ M8 \
  49.         {' O4 V( ]. B5 Y  ~- H2 T
  50.             WebSocket socket = context.WebSocket;
    $ k: o# m1 L/ y
  51.             string user = context.QueryString["user"].ToString();4 N4 @/ E+ \& {
  52.   ^1 E( f4 i  W, L4 Y3 o
  53.             try
    + a% p2 l; n8 {9 l  R  @& y
  54.             {
    0 T4 h% E! i/ j6 d8 _# K; C/ @
  55.                 #region 用户添加连接池
    9 A2 Y! k! f0 y* K& d
  56.                 //第一次open时,添加到连接池中$ Z+ K+ E# c- Q6 H/ g- K. o3 u! P
  57.                 if (!CONNECT_POOL.ContainsKey(user))  z6 ]0 H( r6 H0 c( k7 ]# f
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    - \+ R3 [# m) a! M0 P
  59.                 else
    9 J2 j0 m# s$ d0 r9 W
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新. F+ m  \# y! H9 o- ~2 x
  61.                         CONNECT_POOL[user] = socket;( w% l6 H% R( a2 ?
  62.                 #endregion
    " X- _2 t1 c2 j0 X0 i
  63. 5 D: _. \) P; k
  64.                 #region 离线消息处理1 w/ t& z# h5 x
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    $ @% P1 U) n5 X5 L5 I: @0 [$ |
  66.                 {- Z8 i7 G: H- i6 H
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];9 X& e; k5 V/ w
  68.                     foreach (MessageInfo item in msgs)
    . H) N9 v; {$ }8 d) v/ ^  R8 g
  69.                     {! e- U1 H. D; W$ a* d9 M, ?" T
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);7 L4 v9 t4 a  L/ l8 H+ {( H( \
  71.                     }% K' P' X% g* e0 l! S* b4 u8 o
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    " D$ ]! M% n9 [, _1 t
  73.                 }
    / w  B7 `2 K1 @; [1 z
  74.                 #endregion
    ( r0 t8 w' G( S
  75. ) P6 T' p  x' f6 }- D, q
  76.                 string descUser = string.Empty;//目的用户
    ) a7 |6 O0 n2 V% W4 }" ?& j0 d" t
  77.                 while (true)
    . [( r1 q$ G; G+ d" {% z4 Z. {
  78.                 {4 {% c% [" U0 Y2 `
  79.                     if (socket.State == WebSocketState.Open)* l4 R* |, b0 N  s" d
  80.                     {  |9 P: V: N7 b8 c- C
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);3 @" t4 Z, [3 O
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    - r7 ]9 O) q  q6 c8 |9 S' v% n5 T$ p
  83. ) }! h! e7 D" R* \6 e6 G
  84.                         #region 消息处理(字符截取、消息转发). E/ }8 \/ f# s  d+ s2 v! i4 F/ Z1 e
  85.                         try
    6 x( [0 I& o- \. m5 h, Q
  86.                         {; `( m) o. z1 L% g/ K$ O  B  T* F
  87.                             #region 关闭Socket处理,删除连接池
    ; p4 W! e( e2 H
  88.                             if (socket.State != WebSocketState.Open)//连接关闭" f8 z$ L* ^  [/ e; u+ L( u: n
  89.                             {! C' x! y5 `# |8 P- m$ l
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池6 g8 A' n, f0 f6 c
  91.                                 break;8 {" g  C# k3 V$ u+ q; G
  92.                             }+ A( ^4 \0 F, ^& l$ D) R8 h
  93.                             #endregion
    1 u2 t8 j! ]7 n& v% x" }
  94. 7 e( l3 W: z7 l# i/ h- Q
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息. n, ~3 [3 P1 j* O) V5 h
  96.                             string[] msgList = userMsg.Split('|');3 j& {2 Q5 F/ o+ `, C* O* s+ ]
  97.                             if (msgList.Length == 2)) E! d! }' X- k
  98.                             {- U3 o4 h  ^6 \7 U1 m. F
  99.                                 if (msgList[0].Trim().Length > 0)7 D8 E1 B1 I5 p' @6 B
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户* s7 p! S) o+ ]  C. o9 j5 ?
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    0 o5 ?3 ^- s) v; ]; c9 M. q
  102.                             }
    4 {0 W# J! B; f; a
  103.                             else
    : t# H& w4 `: j( I- g
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    - u6 e! B+ C0 E7 Q; C
  105. ( W6 u" m! M3 |$ f5 d& V
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线- c% a1 C6 [9 V! c
  107.                             {
    2 u* e8 [6 j9 H' u' G* N* C
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    ' P) M( Y4 G/ V: X: v
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)( [* ], [7 @3 ^9 c( r
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    6 x: F. @( V3 ^+ [( @
  111.                             }& C% [% x3 H+ Y2 }" f' D7 P
  112.                             else8 z8 a( Q& X" k& K) H( Q
  113.                             {
    " G! g% `& F. D4 C- }) d
  114.                                 Task.Run(() =>
    2 J1 s, @8 X: q8 ~
  115.                                 {
    5 @2 R* O7 m! h4 v" Z  n
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中/ F) {& U4 f6 ^& u1 k
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    : T7 b! k* o* M4 U
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息$ o8 b1 c2 J% w+ [) [& ]7 Y" [  ^
  119.                                 });- Z4 M( R. m- ]
  120.                             }: _/ {$ J- L7 H% w5 K6 S
  121.                         }. p/ A4 F, n. N5 }  A" U
  122.                         catch (Exception exs)
    4 C. d' k& k7 z- L
  123.                         {
    / u2 u/ M: k+ W7 M+ i
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息3 c" A* q) D; _+ L; F
  125.                         }
    : w: J3 k4 V' P+ }5 ^# V4 S
  126.                         #endregion
    3 V0 }( {9 r1 H/ V. G0 T1 N" u
  127.                     }! v9 {6 i4 _, {$ V
  128.                     else
    2 z# y: c& l' }. k: T- r+ |: D
  129.                     {
    7 d$ D1 K4 r7 G# q( @* Z
  130.                         break;
    % {! D0 `& X% |1 ~
  131.                     }7 ?1 G3 @; K' B/ ]" ~) \
  132.                 }//while end
    " e) }+ f2 P  X( ]) s# L
  133.             }
    $ F2 c* a1 Y4 f4 Y  ?6 I# v
  134.             catch (Exception ex)' H. c3 u2 ?1 i+ B% k: k* u5 L
  135.             {" n) K6 r3 w& k! F5 O
  136.                 //整体异常处理
    0 D, _9 B# G* n: S( L0 r8 e6 o
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    6 N- N8 I) h0 S0 G) p& K
  138.             }: `% `  m$ c7 Z& K  S
  139.         }
    # c9 x% P- b/ \- M+ r+ p
  140.   |4 g( k* L, O
  141. + B2 B1 J, V& Q5 z) K* g7 m' C
  142.         public bool IsReusable' {' P" C: S. O5 e
  143.         {
    6 j( b. N+ ?# g- ~. g) [: t6 C; y. D
  144.             get
    - ^; Z& Z1 n% l% x5 @7 {( ~) G& a
  145.             {
    ' J- m( J# ]7 `, ~4 c6 O0 v
  146.                 return false;
    2 ~6 L* i  k; M
  147.             }
    ! w# o4 r/ d2 V5 R. n7 l+ j3 p
  148.         }6 T( ~! K6 Z4 r8 i+ d- ~
  149.     }; p! X6 f: `7 A! t8 @/ w1 u
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
8 v& o9 M1 |; y( U/ _2 _; R
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-8-4 10:05 , Processed in 0.057850 second(s), 22 queries .

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