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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
# C9 C: o8 ^- C1 D8 m
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;9 H6 p9 o9 B' @9 `+ ^4 ^6 C+ ^, {
  2. using System.Collections.Generic;
    1 e  O1 Y- U$ T- U
  3. using System.Linq;; e$ w. e% U, y
  4. using System.Net.WebSockets;
    2 q: U& y0 b! }3 p2 E+ Q
  5. using System.Text;
      T9 b5 c+ I8 j; M- [* K' L  [
  6. using System.Threading;
    ! o" ?$ o& ?9 Q1 X: g0 c
  7. using System.Threading.Tasks;
    6 g3 n# j5 g# [6 C0 A
  8. using System.Web;0 f0 q0 d1 C  E- O3 ~6 [" u
  9. using System.Web.WebSockets;
    ' f, I7 Z  f2 b- _% }2 f
  10. ( f8 N: {$ a  q8 [6 `& l1 b

  11. 3 J# K+ O( D) |8 u6 Q
  12. namespace WebApplicationWebsocketHandler
    5 o# Q" }$ V4 G3 ?# y1 T) v% W5 ^  R
  13. {
    4 T; R1 `* U* c7 l- }; f# j! ~2 t
  14.     /// <summary>$ a+ q' s3 Y3 M- Y$ V' H
  15.     /// 离线消息
    % _1 n. k) `+ o/ D2 m+ s
  16.     /// </summary>1 e/ R* B# y9 \
  17.     public class MessageInfo
    8 ?7 m; o) z9 M2 ~$ D
  18.     {
    - B( f+ r- ]& n% \; r
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    3 R* v2 ^% O3 a) I3 l2 T
  20.         {7 o  d. @  a3 m9 m& f
  21.             MsgTime = _MsgTime;% H) k; H1 ?1 s5 l' g3 e
  22.             MsgContent = _MsgContent;
    0 M4 q& g  N/ d, x
  23.         }6 \: R2 \9 I" h2 h* j9 n% i
  24.         public DateTime MsgTime { get; set; }
    ( s$ ?+ h$ q( j  |! d* U* Z+ u0 y
  25.         public ArraySegment<byte> MsgContent { get; set; }
    5 U7 @. s: |0 m) e5 ]: H
  26.     }
    - ~  N7 B  [& T9 I6 d4 A
  27. 8 S3 G; z, r( ]/ ~) ~! S

  28. 3 p% x) B5 e) c0 o% ]" `7 S& ^4 J

  29. % G8 g: B8 E) w. ^: {* ?% W

  30. # m4 W  e( `( d6 A
  31.     /// <summary>
    0 S9 o3 |7 t( z* l
  32.     /// Handler1 的摘要说明7 E: E& [  f% {7 t+ K
  33.     /// </summary>6 S% H  S: p  t0 V4 Y
  34.     public class Handler1 : IHttpHandler
    * `1 n0 k1 C: r+ J2 r) O
  35.     {. T: R; [4 h& A/ r6 x8 f; s3 ~( l
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    3 A5 p! u2 D# @( t1 _
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    7 I1 b! O% L: y* d, l. q
  38.         public void ProcessRequest(HttpContext context)# r' Z5 n% L( Y7 \" h+ ~7 T- c) l
  39.         {; I  H: S  J% J3 L! g8 p
  40.             //context.Response.ContentType = "text/plain";
      p) E8 d& E. z& Y; Z0 O0 r* Y
  41.             //context.Response.Write("Hello World");: }  i8 h# G8 b% P8 i
  42.             if (context.IsWebSocketRequest)
    - [+ n+ C7 v7 E
  43.             {$ s, b$ ?" R1 N. N! u5 e- H
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    ) H4 Q" q8 e( f! y- {0 C
  45.             } ; x; K4 ?' y/ H# j
  46.         }
    " n0 r, z: ]6 p# V# o( B/ n3 S
  47. % a+ Y4 m8 u0 [$ w
  48.         private async Task ProcessChat(AspNetWebSocketContext context)3 @" s' ~. q/ Z: Z( \
  49.         {
    2 Y% {: p) G; l! R8 a. y0 S! z& [& v% ]
  50.             WebSocket socket = context.WebSocket;
    4 U5 M: h3 X, Y
  51.             string user = context.QueryString["user"].ToString();' u/ M% m5 n9 M. }8 b; o
  52. $ T+ g3 Y- k- h3 t! c' ?  R
  53.             try
      H" z' V4 y7 h. g# \$ h* _1 z
  54.             {7 {" `9 m& u! B- |& }" e2 d
  55.                 #region 用户添加连接池: B0 m; F3 W- n) j
  56.                 //第一次open时,添加到连接池中% X3 b8 t# D. O
  57.                 if (!CONNECT_POOL.ContainsKey(user))+ s- a3 s) o9 U4 r5 A
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    ' @$ C5 i* Q9 q* t( U4 a$ h
  59.                 else
    $ U* k7 t0 U  z
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    9 E/ q$ D7 t- l! j
  61.                         CONNECT_POOL[user] = socket;; C. |) p  H. V7 |2 G
  62.                 #endregion
    : u+ T+ L( }) V  i. i
  63. : K3 Z1 `5 c% Q5 h
  64.                 #region 离线消息处理9 h$ F. p) t0 Y1 z! |  I3 L
  65.                 if (MESSAGE_POOL.ContainsKey(user))) f" Q& h% W% }7 c# Z
  66.                 {
    1 T& Y& \9 L6 |
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    ' Q0 [& c1 B# G2 S+ _$ I
  68.                     foreach (MessageInfo item in msgs)
    " j9 C; A& C$ r1 o$ U% e2 C( z
  69.                     {  Y% c+ k& H( ?7 R% d$ L+ s
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    / k) B( ?* z4 j% w" @1 U5 V! K
  71.                     }' Z  p3 a; {( X: h
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息9 s) V9 H1 G0 P4 s
  73.                 }
      O& h! R1 p3 {
  74.                 #endregion5 p% f! E1 _6 `$ I
  75. # z; I5 g7 Z8 b" `4 d
  76.                 string descUser = string.Empty;//目的用户
      ?5 u/ D, G; x- P4 I* q0 Q" ]
  77.                 while (true)5 G7 A+ O3 i6 r
  78.                 {
    ' e8 d' ?. T0 Q0 ?6 [9 a* a5 X( p
  79.                     if (socket.State == WebSocketState.Open)
    $ A$ y/ D; ]2 z2 G0 j! a% F
  80.                     {* K7 r6 P# c" ]; _5 A9 D4 h
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    # C: Y/ Q+ G; d/ u0 k6 {
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);) t% @# s3 e4 O4 i# l) F" c

  83. ( a/ _1 ~0 U' L7 _
  84.                         #region 消息处理(字符截取、消息转发)( V8 [4 q4 @: I) g( b/ ?
  85.                         try) R; k4 @. J7 s6 @! N& f
  86.                         {
    ' r) {6 C' X: Z  O2 W) \* T$ o
  87.                             #region 关闭Socket处理,删除连接池7 z1 c5 g2 m# [- L- }0 W
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    " E/ e, {/ S1 [: E+ U5 m; W- M& X( w
  89.                             {
    + m3 l% e% z6 ?7 h  W
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池5 Q$ {+ M  ]; J. I7 b, y% G) x
  91.                                 break;
    3 l: t% O( a" Q3 k
  92.                             }+ ?9 u& Q+ g% P/ U# i7 p  Q' x) `3 c
  93.                             #endregion
    0 ?, M3 P* Q" x9 K1 @
  94. 6 V: V* P2 R# l. s9 }, n# [8 f
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息  f! M* j5 ~1 q7 ]4 |6 V
  96.                             string[] msgList = userMsg.Split('|');
    6 K( _% O2 p) E; c. [( ]
  97.                             if (msgList.Length == 2)
    & L+ `$ A8 ~. S* j
  98.                             {
    / S- Y+ H* c! [0 I; ?; _% u
  99.                                 if (msgList[0].Trim().Length > 0)9 `. {- ], G8 M) [8 n
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户4 T5 a  T4 z: \3 P9 r) U
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));1 F* Y/ P# Q  O5 ]/ V2 ^1 ~
  102.                             }
    7 ^1 y# \2 B; c$ D9 ]6 G
  103.                             else( y; L, Y! D; D* D0 H' A, Q
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    6 X! j6 b; b" z! E5 `% N0 ~8 y

  105. & z, E2 V+ \. v- T7 L5 v& }2 L
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    $ ^+ N! _" U4 r# N
  107.                             {8 F: ~0 }) y- G
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端$ K# L) R4 H) S1 [$ E
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    6 k7 u6 K# \* b
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);7 d  |, r; R( ^7 V1 h
  111.                             }
    3 I% ?3 Y7 F5 `- h  A  y
  112.                             else
    " Z7 i# G1 V2 f" R! x
  113.                             {
    ) k" d2 N  Q# w" u; w$ _& d4 X
  114.                                 Task.Run(() =>
    ; ^1 Z9 O8 e3 j" a$ v
  115.                                 {/ A- u& e! c% h9 Z6 R8 B
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中0 Q" z. r2 J$ ^7 f2 R2 R7 f$ l
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    " J+ _1 l- e9 K* I7 @, y! v, H4 u* e
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息5 `' V2 R! ]# ^- [
  119.                                 });/ P1 K( z8 g: I
  120.                             }
    - q/ d3 t* e) ^" n+ p9 J
  121.                         }
    ; |7 Z  K$ D: w& o
  122.                         catch (Exception exs)# K* J1 E. D7 L9 b, e) z6 n+ D
  123.                         {
    ' F; A9 D" j+ _2 f; b
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    % ^. P. H# C( L: D* ?5 @
  125.                         }
    . b+ f! j- D; S3 ]& {/ ^7 n" }' Q
  126.                         #endregion8 |. i8 U% _: C& k" [' M
  127.                     }
    / |7 x" F) s" x/ R
  128.                     else. i" R& G- ?, l: P! w0 T* l
  129.                     {
    8 L! |# S9 R5 Y4 o8 F3 L
  130.                         break;$ s7 _; }! ]* a% W6 {
  131.                     }
    7 D/ N& o' N0 K' K$ F0 c1 ]
  132.                 }//while end7 f& d% X  m' K9 ^
  133.             }2 C3 I9 w# f! X6 u) k* K
  134.             catch (Exception ex)
    1 ?( d2 I" j% N8 @- k" o
  135.             {
    8 {6 c# H) [$ y
  136.                 //整体异常处理
    ( ]# a: |* J# p5 O5 S# q
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);4 K2 D2 k+ z5 z1 u* v& L! O
  138.             }
    " q% p& u, c# t( f, I
  139.         }  M* @: ?' ?# ~) ]

  140. - B$ w$ y$ z8 Q$ C3 a

  141. 2 h: x* p3 y1 N+ A
  142.         public bool IsReusable6 @4 Z! ~2 P4 P9 H) @
  143.         {
    * S6 F6 L; r) m6 `5 z# J
  144.             get
    * i; V  ?+ ^- [5 l
  145.             {5 j4 y7 b, ]. }( d- J
  146.                 return false;
    3 U% R3 q) M$ M$ d$ k( e# ]
  147.             }
    9 }  G! T  p! j4 H; a- c5 h
  148.         }0 h/ S$ Z3 R, n" j- N- s2 H
  149.     }
    , a2 e7 y, S) P9 T3 z
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
' J) {) Y8 K% y+ N. k
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-6-20 04:19 , Processed in 0.068331 second(s), 23 queries .

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