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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
2 P) o$ I+ h+ z! C5 p' B8 H/ Q; D
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    0 n! i) C. ~; V5 T  ?4 b2 h0 P% y2 R: C
  2. using System.Collections.Generic;
    & c6 B' {. J6 w+ q! C* L) t
  3. using System.Linq;  m9 _  b2 F! O2 T4 g
  4. using System.Net.WebSockets;
    9 W8 a' j1 J& F' _8 Y5 p/ g# ?
  5. using System.Text;  ?0 J: z( U8 T
  6. using System.Threading;+ |4 G, Y+ p, @) C
  7. using System.Threading.Tasks;
    7 U4 z' V, x# _% Y
  8. using System.Web;0 A* P. k9 }8 D) B  U4 T
  9. using System.Web.WebSockets;1 w! u, z9 v! ]  x2 \$ p
  10. & T: j: G. x2 ~, e& y: t. _% i
  11. 9 e1 P& G# o/ u- B) S) Z3 z: _
  12. namespace WebApplicationWebsocketHandler
    , w  J+ ^% U% Z0 z" f0 x7 ~
  13. {
    ) I0 U3 ~5 c, k8 d& ]
  14.     /// <summary>
    & P) @) s7 l1 k5 @
  15.     /// 离线消息+ z2 s& t/ o! l+ f; b  R! c6 f
  16.     /// </summary># [% [# D9 ]' J6 G
  17.     public class MessageInfo8 a' w. p/ L& m" S9 ^, U1 M
  18.     {5 t0 Q9 F" d( P& d. G0 {) T
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)  ?: ?$ ^; J) o  {& K' K
  20.         {1 }8 r$ j: n  Z1 @, Q- P* h# k
  21.             MsgTime = _MsgTime;
    5 m3 `* X6 G' [7 P
  22.             MsgContent = _MsgContent;+ Y! m( A" B- L
  23.         }
    / _0 [. M! F. L+ g& i+ A, j1 e' q
  24.         public DateTime MsgTime { get; set; }
    : F* Q0 S" A* G0 R/ W6 i
  25.         public ArraySegment<byte> MsgContent { get; set; }8 ]& F( s* E  |- ?+ a. Q* d
  26.     }
    # D$ @; p3 ]; Q6 u( P
  27. ; n. q% _$ e* d( O
  28. % m& r- z4 f. _- E9 r4 r5 F1 y

  29. & M" T/ ^, i0 }" S$ D

  30. 9 k9 `* v7 \9 |+ Q
  31.     /// <summary>
    $ {0 a; K. p# y/ h8 F! z
  32.     /// Handler1 的摘要说明
    2 S3 p: j! Y5 n/ t+ W! V
  33.     /// </summary>
    * O- l6 c. x- E) G2 T3 C5 Q
  34.     public class Handler1 : IHttpHandler# a' g, O6 J3 F5 n( S
  35.     {
    ( d: U9 |7 E4 q$ \; j) b
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池1 Y" d  |2 y3 b1 P8 s7 Q
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    1 {0 n9 s/ A( u- `7 q6 U5 @9 g; x: n3 P
  38.         public void ProcessRequest(HttpContext context)
    / k- ~1 K0 H  K" \! p4 [6 N
  39.         {
    . e( g! H# E. G
  40.             //context.Response.ContentType = "text/plain";7 k& f0 Q2 Q1 U7 W  e1 F* x. h
  41.             //context.Response.Write("Hello World");
    2 B2 Z7 ^  E  o. y
  42.             if (context.IsWebSocketRequest)# Z# x8 H. S$ X0 n6 S+ a% J0 n
  43.             {+ i. D7 n- h" f. x' J) ?
  44.                 context.AcceptWebSocketRequest(ProcessChat);; d7 D* u4 q7 t
  45.             } : ]* z( G$ _  K# M# f! {- j
  46.         }
    $ ]% `1 [, v2 m) L8 I0 ?* i( \) K
  47. " V/ x: L4 r. ]- @$ o4 c
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    7 s( y/ W5 N8 q: W' c$ l; S
  49.         {
    + ?  n' h. ^  E5 |
  50.             WebSocket socket = context.WebSocket;# |. C' S5 E& c2 y, r" ]/ m* y
  51.             string user = context.QueryString["user"].ToString();
    ! _( o4 k9 n& U" \- A6 R0 v
  52. 7 J8 ?* P* z( l7 o3 d( d' }
  53.             try
    + k/ i% f' \. i5 |5 N. W
  54.             {
    . V( g  X( Z" g+ X# ~" b
  55.                 #region 用户添加连接池  |# v" c; z" f" o
  56.                 //第一次open时,添加到连接池中7 H8 Z1 c+ `" ?) @
  57.                 if (!CONNECT_POOL.ContainsKey(user))/ s) ^6 a9 v0 r% O
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    ( o  V5 ~/ b) g$ e( X/ c
  59.                 else0 H9 P# a$ W) |, \
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新* o& _1 X" G- k( Z0 _5 w
  61.                         CONNECT_POOL[user] = socket;
    / |! y  o3 D  K; E
  62.                 #endregion5 ?- k1 L+ Y/ }' f, }: U, W; a( a
  63. 3 R9 E0 q9 J& ^
  64.                 #region 离线消息处理, V  `9 X. @$ J5 G% t' f
  65.                 if (MESSAGE_POOL.ContainsKey(user))& Y4 W( t9 m5 \0 e) ]8 ]- ]
  66.                 {
    4 Y; J, P5 x& u5 H
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];3 C* s+ @/ A2 ~2 C! z. C! o
  68.                     foreach (MessageInfo item in msgs)
    ' k7 q, x; ^6 }6 r/ s- N: W
  69.                     {
    5 ?7 g% B# ^5 L, `, ~6 h$ C, N, B
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);0 `* H* i1 w: m) r/ \5 T1 J* r
  71.                     }4 q% X3 J* v* H' r; W, V
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    # m+ X6 Q' O, X4 P- y3 V2 o# Z* o
  73.                 }6 j" _. Z! ?4 u9 H
  74.                 #endregion8 J* n5 i  `+ g4 L" ?" J7 f

  75. 3 ^. ~. M+ P+ e2 ~$ g
  76.                 string descUser = string.Empty;//目的用户
    2 j, H' e" z7 k" c. Q/ s' x
  77.                 while (true)9 G$ [1 L6 R& A9 v5 j
  78.                 {. k% n& I% _" R: Y/ O
  79.                     if (socket.State == WebSocketState.Open)
    % z; d" i0 @. r. b: m' L) F
  80.                     {# e  W: e* H, i  M  G" i7 N+ ?
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    / A( f2 {. }/ H: J- h
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);, d& h( Z% j1 r1 v4 u
  83. , {& ?1 s7 M: R
  84.                         #region 消息处理(字符截取、消息转发)% s5 E4 n# v4 i/ {/ M! M+ m
  85.                         try4 Q% T* b3 a/ A+ o* {* ^
  86.                         {
    1 B( O6 i0 n! ]& L7 [7 K1 V9 X
  87.                             #region 关闭Socket处理,删除连接池( o# R; J2 s' a: s
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    : X1 r2 U) G) y( \( S( r
  89.                             {
    8 s" X' K+ T: R, l. Q+ I+ ?
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池' h3 ]. |4 m9 s( o! o
  91.                                 break;/ d. D$ F9 h+ W3 G6 n6 v- z; }
  92.                             }
    4 p6 i9 o4 g) m
  93.                             #endregion1 g) K- [9 K4 u" v8 B

  94. % @0 A" \4 q' ]7 v4 |+ y
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息( [6 }% l0 V, d+ @. P: C; K
  96.                             string[] msgList = userMsg.Split('|');" \0 [5 J) X5 f- j9 i
  97.                             if (msgList.Length == 2)
    , p/ c' _$ R% x$ E
  98.                             {
    / h+ ^4 w0 O8 g4 U* A% O: M# B
  99.                                 if (msgList[0].Trim().Length > 0)
    $ y% V+ o! Y) s3 O2 p, \
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    / F2 ^* H7 Y- V5 B6 F0 `
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    4 U+ \; U: K% B% _' E6 P9 \- ~
  102.                             }
    . a: ?& w6 t# J
  103.                             else
    1 n) s0 M9 ~" Y
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    " [! N2 a) u" o/ l

  105. 3 s4 n; N3 ^! [- g0 Z- E" w2 v
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    : `; d6 J% n0 M; Q0 x  J! p; R
  107.                             {
    , a; d2 C$ K3 V1 o" Y2 B
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端: i# w, o6 b1 {! n" |; p  J. C. D) j
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    6 e5 }" l1 |  A: |+ ^0 a
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);# I2 g3 c8 k" b+ r
  111.                             }
    . L6 A) t( s+ ]6 n, l1 ]! Y/ l
  112.                             else
    , g2 @4 |8 [: f
  113.                             {
    9 E% e! M" X' I( [( e3 d
  114.                                 Task.Run(() =>  [$ B& F% D- L9 c7 |- z! R" B
  115.                                 {: e/ D8 Q- u" l( I
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    & `# S. C5 Q5 y0 s6 U
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());, o0 b  k( O7 E6 w2 Y- M
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    ' T- o; Z/ C$ s5 E: W% W* M1 V
  119.                                 });
    7 y) o0 K, l: t6 m% i% [
  120.                             }
    . Y$ g% r) a7 w
  121.                         }
    . \2 C! [9 m* [' O8 y
  122.                         catch (Exception exs)+ N/ N' b% `. \, o% |  j* M
  123.                         {
    1 m' I; [- w$ h4 c  }! x' J
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息* S3 n* n/ L4 h% D8 X
  125.                         }
    + S, j( V1 d7 ~# S% ]( j
  126.                         #endregion% d9 a% e1 z/ D/ T/ c6 d
  127.                     }1 _+ S% r& y5 m" T" ~# w- s2 w
  128.                     else# v) S* {2 V% H! F9 N
  129.                     {
    1 ^, K. U- n4 ^0 K
  130.                         break;
    " D8 l0 e" q' x4 d! t; y9 r+ r
  131.                     }8 j8 c+ e! S$ I$ K2 G3 [* F! k0 @
  132.                 }//while end8 _8 n9 e4 Z4 J9 m
  133.             }5 g& ^. Q0 V! ~6 q
  134.             catch (Exception ex)6 g1 w7 Z  t: G/ `1 @9 }
  135.             {
    ) z+ W4 @" p$ y
  136.                 //整体异常处理
    ' W) `: W! a7 w+ g+ h8 X! @$ {5 B
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);9 x  i' B1 o7 W+ y
  138.             }6 a: s% J3 C" }- J
  139.         }
    ! P8 |6 ~( z0 V$ p% n6 v
  140. / n  c. f0 O  o/ s2 w
  141. + T' B9 j' G. {
  142.         public bool IsReusable% W1 i/ ]( D" ?' A1 L
  143.         {7 q' d+ G* X0 s2 L
  144.             get
    3 L: V! L: F/ C0 A4 y  D1 _
  145.             {
    ; G2 ]3 L5 C% d% R
  146.                 return false;4 f7 L: k0 n6 ?+ v& ^* `# q0 O4 Z
  147.             }: J- k3 E' N2 _& r, J- ~4 v/ j
  148.         }' N, H5 g4 Z% H! F
  149.     }3 R2 X- o, R- D8 {' z0 R! L
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
+ g( T  [. H7 ^& n; q4 _
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-4-28 17:56 , Processed in 0.175879 second(s), 24 queries .

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