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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
4 E' l# h' ?4 G) m8 d2 M' {
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;. y* W- b, @+ Q6 [  N# k5 i
  2. using System.Collections.Generic;
    ; E/ h1 m5 [9 |. O: f, e( ?9 P: E, X
  3. using System.Linq;9 y' r) `8 n) \. |3 e0 p
  4. using System.Net.WebSockets;* b, y0 G* x% Y1 e% w$ U
  5. using System.Text;7 I$ L) S, K( S# r2 |
  6. using System.Threading;
    2 h" l2 z* g6 S$ I
  7. using System.Threading.Tasks;- Z) J) _$ O; \; R4 G4 V7 t" }
  8. using System.Web;4 R! ^" F# T& P$ ~* Y/ y
  9. using System.Web.WebSockets;
    4 A$ \5 q& c% l; b% x: i4 B2 v

  10. 5 E8 W' Y; P- P0 K0 i. ]- H

  11. / {0 A' ^0 v& m5 h0 Q0 b# p
  12. namespace WebApplicationWebsocketHandler9 I( j% |# X( A3 T% U
  13. {+ j$ \# ?& p: w4 G) d. P7 N
  14.     /// <summary>
    5 a2 `" z9 B% o1 k" {5 V& D: L: j
  15.     /// 离线消息5 ^$ G6 l9 L. s* G8 T; k
  16.     /// </summary>1 |3 R, `9 L9 S% L8 m) ~
  17.     public class MessageInfo' o8 M6 k" C2 T; ^* c
  18.     {
    * i8 w; Y  Z7 C3 \2 n
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    8 G2 N0 b  c; l( V8 ^+ g, t
  20.         {0 [% T  p7 M6 F. j6 S
  21.             MsgTime = _MsgTime;* q- D7 O( y5 A7 e
  22.             MsgContent = _MsgContent;
    , e" a/ Y1 T3 t/ p0 S
  23.         }
    , S* ~4 R! ?6 g( v5 d& }
  24.         public DateTime MsgTime { get; set; }( n2 B( Y, N, f+ Y4 C9 u
  25.         public ArraySegment<byte> MsgContent { get; set; }0 ]- T& m- e& K9 J3 h# Y8 c" r
  26.     }
    . \* h5 ?& G# d! t

  27. 6 `$ q1 S, D% D; p: d1 I

  28. ' P9 g7 _& @: m, \
  29. $ b" R! M0 c* m# O0 k% T2 f
  30. ! _% l% s( h% D0 v
  31.     /// <summary>
    1 _  Z" s+ B8 x1 H$ ~
  32.     /// Handler1 的摘要说明
    , e. a' O6 r! x# o
  33.     /// </summary># G% ?! [/ h+ U3 s6 M3 V4 ^/ R
  34.     public class Handler1 : IHttpHandler
    , F+ q" t, _3 l, W6 d# a
  35.     {' Q* i+ x+ U' Q+ c8 I; _) S
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池+ s% v/ j8 {: K; E" z9 o( w/ Q
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池# \8 `6 X9 Z" h1 H
  38.         public void ProcessRequest(HttpContext context)
    1 r3 L- {: j# a( G- w' d( _
  39.         {
    3 ?4 H2 J$ x  p) [4 B% t7 ^
  40.             //context.Response.ContentType = "text/plain";
    - c2 ]. a( q7 ^
  41.             //context.Response.Write("Hello World");
    3 v! [) E: C; j+ _5 [0 s: K# L
  42.             if (context.IsWebSocketRequest)
    ; m2 Z  x! @6 p+ P" t
  43.             {
    9 f2 {( Y2 x* N' `
  44.                 context.AcceptWebSocketRequest(ProcessChat);: k- r/ N( C7 `4 T
  45.             } ! m. k$ _) m4 x# Z
  46.         }) Q9 A# O# Y( I% x, Q$ U
  47. 3 p: C# z" z; `* F$ Z
  48.         private async Task ProcessChat(AspNetWebSocketContext context)/ t' O% [% B: Z3 y% X3 c0 d1 [) F
  49.         {
    / D1 y0 l& w6 N  y
  50.             WebSocket socket = context.WebSocket;
    % y6 m5 h9 _% i& |/ _
  51.             string user = context.QueryString["user"].ToString();
    6 s1 a* c# z5 m3 n7 l: U

  52. , _- n. {) Z3 V" S, o
  53.             try0 G% u0 r0 F3 }& B
  54.             {
    , i, J5 K9 i$ b. S- U
  55.                 #region 用户添加连接池7 V1 |/ ~2 T" q& G  ~
  56.                 //第一次open时,添加到连接池中
    ) N4 D# l/ E# L3 `4 A
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    / [+ W3 `% ?: ~6 ~
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加$ t# e& W" W  D) r
  59.                 else" `. r. x  j* ?. r5 T5 \. k
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新' X1 y) m& n# F" N
  61.                         CONNECT_POOL[user] = socket;. J! j) q! u" ^8 l
  62.                 #endregion' F- l1 t/ h& f3 J* O
  63. ; |, j; ]: r8 ~( X8 d. \2 k
  64.                 #region 离线消息处理
    & `  r& p' e" _# Y6 T% d
  65.                 if (MESSAGE_POOL.ContainsKey(user)). k+ }4 s# {0 p/ Y
  66.                 {
    3 v: G2 u% T% p1 |
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    ' W. r% I  d% N( T
  68.                     foreach (MessageInfo item in msgs), S! R2 s- g0 m( ?( v! n
  69.                     {
    4 M* S& a, r1 u4 B( v: i6 p
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    . ]% ]& [6 j$ O
  71.                     }
    $ s- `. ^+ W! [4 j
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息9 A( I, T0 w6 B+ i5 ]
  73.                 }% v; q7 e8 v  u& a. a$ `$ b0 C
  74.                 #endregion/ S$ e1 |/ [8 C8 p( S/ N4 [) p

  75. ( W9 |& R+ P4 G& ~1 J1 h
  76.                 string descUser = string.Empty;//目的用户
    ( i+ z" `1 |+ s
  77.                 while (true). N/ H' O: T3 G- f0 P7 E
  78.                 {
    + F5 J* n* v) p
  79.                     if (socket.State == WebSocketState.Open): H3 m- I. A  w0 b  c9 q) Q
  80.                     {
    1 M5 C8 m* p* E  v$ q
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);1 o$ ^& ]9 c! M$ \5 D
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);9 g- T, M0 b: G6 O. o( N" k
  83. ' E2 T4 L) `3 a; [- s3 I
  84.                         #region 消息处理(字符截取、消息转发)
    6 V, `: j% {8 C3 w2 H- O5 s+ x/ n
  85.                         try
      d$ y2 G; s8 H& L4 W6 d
  86.                         {
    2 W: r6 t. U" r4 u0 l, v. z/ Y
  87.                             #region 关闭Socket处理,删除连接池# G& y0 P" c4 G% |3 |) i& w0 n
  88.                             if (socket.State != WebSocketState.Open)//连接关闭0 O# t6 c% s7 H8 V9 ]
  89.                             {
    5 \. @7 W* M% b
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池6 X8 X1 r1 v1 C+ G1 L7 C% K" i# E
  91.                                 break;
    0 E, d& u2 E; A) p7 V: x
  92.                             }
    2 X  V% v/ I- V2 I1 }! G
  93.                             #endregion
    4 x) G2 j' q% x

  94. ) _& G, j3 I) h8 i
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息+ B0 G) l8 l: J3 {- r
  96.                             string[] msgList = userMsg.Split('|');! p& h1 u0 c9 `) V* A9 W
  97.                             if (msgList.Length == 2)
    / R$ g( T3 d* K: N! f7 g3 ?- `; U- }+ j
  98.                             {% H/ U/ T- j6 m
  99.                                 if (msgList[0].Trim().Length > 0), g2 f* @* C8 a: a* J8 N
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    % T3 T% H) A9 Q0 {5 {$ F1 I+ h6 Z# q
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));+ b2 B1 B0 _* W8 H# k: P0 Z
  102.                             }
    7 m3 M2 ^, B9 D9 d+ M
  103.                             else
    8 K( i% m+ I6 x" u" P3 h
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));1 e; `, j) s& {6 L" Q
  105. $ V1 S" ?7 d/ ^
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    5 A8 ^& h9 w* X" h% j6 w/ H
  107.                             {$ D/ H2 \% [0 M* F$ E
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端6 O6 A; o1 D& J6 }
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    $ o9 {- {7 n, C# |2 A- U4 g
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    $ e, D- ?9 M* ?% j, p) t# T+ @
  111.                             }% W5 R/ {7 v3 n% c) ~" Q. x3 s0 R
  112.                             else$ S, S7 Z7 D/ f4 Y% F6 {* B7 I7 N
  113.                             {$ {# |1 M, A) q8 |
  114.                                 Task.Run(() =>* S# S) O) a7 Z1 X8 J7 t
  115.                                 {7 Q3 i- X$ E. e- C' i
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    $ ~0 W& o9 ?4 n( N$ I
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    # e' @9 o0 A) Q9 m% o5 x
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息4 p4 P% P* ^- w" U, F1 T2 C
  119.                                 });
    * x! i0 Y3 a4 k0 Y$ a1 d
  120.                             }8 C6 W9 o" M9 u. ~2 X% T
  121.                         }
    & \- g- X8 y' J! i
  122.                         catch (Exception exs)
    ! U+ `+ ~3 m1 v! Z" a0 W; b: P
  123.                         {2 l& Y) Q- n# L: o3 c4 ^0 t$ l
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息6 {: j9 P& r$ O
  125.                         }
    5 t" D* v# i7 e" R% r6 G% u
  126.                         #endregion
    " N$ U( I- w  u, u- x  c. W: E
  127.                     }
    / L+ Q- J& `! u2 }& I& W% M- o( B5 @
  128.                     else% l! A1 ?8 x8 a! n
  129.                     {5 H. E9 q# E. t0 q, @& h
  130.                         break;. x# s8 W0 O2 ^& e8 R
  131.                     }
    3 i" B4 \5 M, |, c4 o1 V
  132.                 }//while end6 y3 J1 l8 X3 X1 |# L8 j7 ?/ L! q
  133.             }4 U3 n. i& o1 s. l  T- V5 F- L
  134.             catch (Exception ex)) O7 t. D  l1 ]$ U
  135.             {0 w! N; E- f0 q" P/ |
  136.                 //整体异常处理
    7 V& c  l. c" P% n" ]' \( y8 {1 o
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);( P& y+ z( E6 E. M
  138.             }! m3 g: p3 e8 V& U& l
  139.         }1 Q2 k7 P1 W' O# r/ {- F8 p

  140. , o$ l; ?$ u/ g1 }8 l2 Q: w

  141. * q) ~, I( w, Z- q( R! b, U+ `# j- V) |& k
  142.         public bool IsReusable
    1 {# p; \- v: _( D- e: p: J
  143.         {
    ; L" g4 `. g( ]0 F: ^0 ?/ I
  144.             get: t4 K, D; ?: W/ H
  145.             {
    2 f8 @; x  P2 {& Z# V0 ~* n. b
  146.                 return false;1 |7 v8 u3 i4 i5 k6 a: a4 W
  147.             }
    3 I2 D. c1 j6 C5 y; d
  148.         }/ ~: b; I* l% g4 @
  149.     }
    ( z: }0 D, j! b0 b+ }. q: H
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

% a/ ?- u) S: q! A$ b& b1 f3 {
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-9-29 07:33 , Processed in 0.119912 second(s), 25 queries .

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