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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

( a# A9 b' ]4 v3 o
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;$ `9 y7 e( R5 W$ r
  2. using System.Collections.Generic;
    $ y3 J, M2 W1 @5 p0 u6 I4 a
  3. using System.Linq;) f1 N/ X3 v# s/ ^2 C
  4. using System.Net.WebSockets;
    4 ], g! m0 q9 X
  5. using System.Text;
    6 ^7 O5 J% c0 L# D6 W% C$ L. y
  6. using System.Threading;
    ( X# W3 [) ~: F9 {! O6 O
  7. using System.Threading.Tasks;, p& P# v: o% _5 T+ i
  8. using System.Web;
    - n3 {+ ~( F) p9 F6 ?/ W5 D
  9. using System.Web.WebSockets;& G# p1 l0 e3 B4 o7 J* l

  10. % c7 f4 C% S3 i$ P$ ?- B

  11. " Y7 v# V4 g  \0 l: Q% ^4 Y
  12. namespace WebApplicationWebsocketHandler
    0 a6 O8 Q$ Z! ~5 I: ]# Q
  13. {
    : o; _- D) t# T* u& k7 i7 }
  14.     /// <summary>
    6 H! c. D# H* C) I6 o5 K0 h$ w5 l
  15.     /// 离线消息
    5 c' O4 e- G) Y1 W  n4 |
  16.     /// </summary>
    ! j" }& O" y6 L
  17.     public class MessageInfo
    ; {! p# v0 X2 P
  18.     {$ n8 R* E- r4 W
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    " B. f! n( A6 }" X1 v2 x4 }
  20.         {- e' T- y) Q, c6 [8 k- S/ c
  21.             MsgTime = _MsgTime;) T. v2 {2 z5 j0 ^( |8 T
  22.             MsgContent = _MsgContent;
    ' Q1 P, F  ?/ R8 X
  23.         }7 J) ^. Y& V" Q+ f6 E. s
  24.         public DateTime MsgTime { get; set; }& I+ _6 `8 W( K6 O: X) f; `% V
  25.         public ArraySegment<byte> MsgContent { get; set; }
    # w  Z8 x; _& h2 W% l
  26.     }2 X* Z) Q9 S" k, o/ H

  27. : S4 x/ H8 `, a; C) a( }# U
  28. 3 k0 E3 u/ i) i. C

  29. - f; l, n$ c5 |" ?( w

  30. . y0 t. k2 g4 r7 A8 u
  31.     /// <summary>
    + U$ v/ W+ j% }" c& A7 q0 m, n
  32.     /// Handler1 的摘要说明/ H2 h$ z- J' X" L9 D$ r
  33.     /// </summary>" N: Q4 {7 X8 A
  34.     public class Handler1 : IHttpHandler+ w6 H% o* S5 \8 m7 ]: ?% B7 \
  35.     {
    6 ?( v$ Y3 x+ {  J! y, Q4 H
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池2 d8 V3 M/ j6 z1 i% R: g# }+ I8 h
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    * y3 z2 N- U4 f# u/ f0 ^5 _- {! m
  38.         public void ProcessRequest(HttpContext context)9 Y3 c+ f! f4 [" ^7 ^  M
  39.         {% v8 E9 v7 K1 A  j& C% N
  40.             //context.Response.ContentType = "text/plain";/ A' k  r3 ~, v6 C0 x3 x7 @; G
  41.             //context.Response.Write("Hello World");
    & s+ E  z4 G* ]1 @
  42.             if (context.IsWebSocketRequest)8 {5 o0 h) n% w. k  [# S3 ^3 |
  43.             {; P) t; C; Y; i! E
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    0 {, i8 M* ~, V
  45.             }   ?2 h& K/ U$ B: H# c0 @8 |
  46.         }
    : Q- d# j3 a9 A! m5 ?, ^

  47. 5 c! q! e5 |% @! C
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    / d0 v9 ?* ]" F% A- H8 m
  49.         {
    5 Q' L" f4 B% P5 @- a+ C
  50.             WebSocket socket = context.WebSocket;' [) _7 ?8 K4 g, {' Z/ m5 }7 d! P
  51.             string user = context.QueryString["user"].ToString();
    : x6 z$ o+ Y0 u0 [2 r) ~1 F

  52. & n# ~. `( h) y' a' }# j
  53.             try- [+ q1 V! }' w3 E4 d
  54.             {
    2 C* G# Z! z2 `" }. |
  55.                 #region 用户添加连接池) p+ ^) |$ U( q. W
  56.                 //第一次open时,添加到连接池中2 J6 J) n; X: c9 P" s( l
  57.                 if (!CONNECT_POOL.ContainsKey(user))% c: X9 a8 s1 P1 t8 f" J% R
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    * V1 a' x; L) F( J2 W9 W$ I; M. e
  59.                 else; q) |  Z; ~% z( o
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新  z" C8 T5 Z9 k3 P% B2 R/ Z$ |3 Y
  61.                         CONNECT_POOL[user] = socket;- M& F/ A! u* }) P8 C1 \% k% l& e
  62.                 #endregion' J, k( K8 j" e

  63. - e" g6 J& y# K
  64.                 #region 离线消息处理
    ! K% H: u; {& V' P+ |- i
  65.                 if (MESSAGE_POOL.ContainsKey(user)): z/ Q' k+ D/ r! J2 d" y
  66.                 {9 O% p$ W( r4 `/ y+ t
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    % {! Z1 F. r, `, V6 Z+ [8 v
  68.                     foreach (MessageInfo item in msgs)* Q- H4 y& ^$ I. @* y8 T3 [1 ?
  69.                     {
    ' d; {$ U9 _3 |# U3 [, @4 W9 L
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);! ^# p% H  x2 o" E' ?
  71.                     }
    5 Q8 ^7 t# n: c  k
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息- U6 J9 n# L7 u: P
  73.                 }0 B0 t7 T, M/ x
  74.                 #endregion1 c: \* H& Q& `, N. h8 _2 Y

  75. 9 E/ d: g' U/ l& {! |3 |% a# _
  76.                 string descUser = string.Empty;//目的用户
    8 c% V# k% l6 v6 @% L
  77.                 while (true)
    : d5 j* q( L9 i, e+ g! x
  78.                 {2 L7 \1 r6 B% }/ O4 ?5 _' a
  79.                     if (socket.State == WebSocketState.Open); ?: t  |' H) Y9 m3 o2 ~8 u
  80.                     {
    " S( c/ S4 e5 S1 I. o7 h
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    ! [; _1 K0 R4 N/ G3 S
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);3 X4 Z+ u! M: }( R9 R

  83. * q( |7 C+ F* ]+ }$ @$ b
  84.                         #region 消息处理(字符截取、消息转发)
    : n: d! S" j3 n" }  o3 b) N
  85.                         try- m) q( n# n9 y- _8 W
  86.                         {
    1 r, B0 y9 r2 N. x! z' S5 L( P
  87.                             #region 关闭Socket处理,删除连接池. Z7 o& S/ }2 O6 @0 E
  88.                             if (socket.State != WebSocketState.Open)//连接关闭  m. X8 G7 M0 n- z( ~
  89.                             {
    4 @6 b: r4 q7 m; |0 X6 G2 ?( x+ `' X
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池& _5 J' @: j) e) p3 O
  91.                                 break;
    7 F8 C% g! e0 ~4 U1 C& ~4 V$ l+ l* o' ]
  92.                             }; y5 h  h* j/ m" o  P7 e5 I
  93.                             #endregion
    * }; h; M/ X+ {# V( i

  94. 8 F2 g$ ~7 f4 G* W+ Q; J! [- Y7 p: |! u
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息1 }+ x- g& o2 Q* l! ?
  96.                             string[] msgList = userMsg.Split('|');5 O& H- U4 X. j: I: Q+ E
  97.                             if (msgList.Length == 2)5 k8 H* z: P# u8 H
  98.                             {: M' O) m% n, c/ ~& g
  99.                                 if (msgList[0].Trim().Length > 0)
    $ X( _0 S1 z0 u2 i0 E7 D
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户+ c$ W: u7 b2 R0 ~
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));* H$ V  h* o4 @& x
  102.                             }
    ) t9 g( |* B/ y/ @8 Q1 c! ]
  103.                             else5 T8 U: j! k0 O& n! _4 ^  c( K
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));# E; X& ^, p$ D8 y1 Z
  105. 9 n  Z) M) D( H, X( {% }
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线* e5 q4 `, T/ g! W) R/ F
  107.                             {
    2 P/ Q/ K" ], b
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    ' k( z& u6 V$ F  y% L
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)7 g) G5 _! _' b! m- j8 }
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);3 y3 G/ B7 E& n3 s
  111.                             }5 R) I8 Q& S$ W9 k' M: ^+ p
  112.                             else
    5 r+ n. {: L/ V* B0 f5 F- Y
  113.                             {& o6 I* i8 i, B0 r
  114.                                 Task.Run(() =>
    1 w7 N8 _- j, z2 h: N
  115.                                 {) z0 w0 ^, A* L, D* h6 Y: y
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    ' G& z+ |( B9 n
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());0 {, o  E7 K1 k9 E% E; m9 z
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息9 }0 b% E4 L& ?3 W' }" O. K
  119.                                 });' ^6 }( M) Z6 z+ I6 U8 W; i4 c6 N, z
  120.                             }/ W) i1 q7 J( ?4 ^
  121.                         }
    6 C6 M& E3 f0 h" t
  122.                         catch (Exception exs)- U6 N4 L! k& O4 }* O( ~4 Y- n6 X
  123.                         {. j5 U% U$ V. Z: A( _. A9 H
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    1 N4 M0 M: N: y
  125.                         }
    ! M5 r3 B+ ^7 F. t1 g! s! B
  126.                         #endregion( Y/ t. u8 C0 _+ T4 T# C
  127.                     }% F  Z; S: a6 H
  128.                     else
    9 q' k9 r! x9 e7 F) E
  129.                     {- y* L3 q0 t. V4 t1 y0 Y9 |
  130.                         break;( j8 |1 y9 v  U& h
  131.                     }
    ; H5 t9 J8 e- n, g5 o+ Z$ x; Z
  132.                 }//while end
    : k; N. D6 g3 M/ q  e
  133.             }
    % T0 W! u; |! B" @+ X. R. ^8 q
  134.             catch (Exception ex)
    + c/ Z7 o$ Q2 }) B( `/ L: A
  135.             {
    6 l9 M5 g$ }. q2 `+ }! `0 f
  136.                 //整体异常处理. `$ X3 g+ H& Q2 A( h
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    ; }# P" Q, w) ?" \3 ]$ h) f' u& l
  138.             }
    1 N- A9 a2 t" O4 x* l- U
  139.         }
    ! u/ q! d1 s* K/ Z' m* J9 E

  140. + k, F6 J/ B2 Y2 e3 B

  141. , }; H! ~' H6 B( T. S
  142.         public bool IsReusable
    " x# q8 g% @1 p! Q5 P2 s
  143.         {0 z0 c9 @% j4 d- J1 j
  144.             get$ p# Z7 Q; x: N$ d1 t! O! d  I0 D
  145.             {
    ( r+ K+ z! U9 W7 d$ Z1 U3 ?
  146.                 return false;  G' O3 z! N  f: i
  147.             }
    ) N5 S+ r; i- ~, K
  148.         }
    4 m" O# B/ [5 _8 F& _1 A
  149.     }
    5 c; A8 |: ^0 Y  o! ]$ g5 M/ Y
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

+ Q( T1 Z  @% M+ ]1 Q! D& w
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-3-17 20:19 , Processed in 0.060349 second(s), 22 queries .

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