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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

  c$ }- I  [9 R+ v( a/ O
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;0 M9 Y, w2 ~  w( X
  2. using System.Collections.Generic;
    5 e7 `* ]% G8 O9 u
  3. using System.Linq;
    ' j2 o; h  n& E: j7 D2 A
  4. using System.Net.WebSockets;) B  J( O" y3 {0 f
  5. using System.Text;
    $ R. d! L" `! n
  6. using System.Threading;- l+ v9 p2 }% B) n9 Q. i
  7. using System.Threading.Tasks;- |$ t% {( l2 N4 Q0 ?
  8. using System.Web;" F" Z: P+ v- p5 I  ]0 {) {4 V) K6 Q
  9. using System.Web.WebSockets;% ~+ r& n- O7 ~' b3 y* U

  10. 1 Y( X* |* L1 X6 t& e! z% T1 U' p
  11. 9 o8 z1 u; U9 t& t* v) B5 z: O
  12. namespace WebApplicationWebsocketHandler
    4 l( S/ X) A4 i9 Z( b4 m! i4 v) t/ }
  13. {
    & ^9 j4 c7 d' |, z5 Z1 D9 g" x
  14.     /// <summary>
    8 N) p' U) X6 s( ^* p/ t2 J
  15.     /// 离线消息: O: F/ u1 d4 P
  16.     /// </summary>
    & g, g. O  b! X
  17.     public class MessageInfo6 u% O8 m+ I$ n0 L& g  s
  18.     {
    ; X9 ]6 X% L( u% q& @
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)/ g2 X2 _4 G5 |" O  |1 ~
  20.         {& o: B8 n- x: u3 k# k- e
  21.             MsgTime = _MsgTime;
    6 o  H5 \# j6 t: o' t0 y2 l
  22.             MsgContent = _MsgContent;3 g, q  b2 X) F  U' z6 i8 G$ ]1 T0 \) d
  23.         }" t( Y9 p8 v5 O3 p3 c/ D6 z9 B. a9 }
  24.         public DateTime MsgTime { get; set; }
    . S9 W+ s! j$ z
  25.         public ArraySegment<byte> MsgContent { get; set; }" X( {  c( m4 c, s. S* l5 D# N
  26.     }& O/ f& T) O1 @# h$ M, B( \
  27. + b2 F+ f1 d: `9 g# D
  28. * D4 v7 U( k* C/ E5 j

  29. # P& [; A/ U4 y& [% N
  30. 3 ?1 v6 }# z% r" s3 G% x# e
  31.     /// <summary>
    ) k! D$ o3 R& ]* x, F8 K% t
  32.     /// Handler1 的摘要说明
    5 v9 e& K% o5 A# U0 j. {. x
  33.     /// </summary>
    9 ~4 q/ j9 a8 [0 b9 {; C1 n) ^
  34.     public class Handler1 : IHttpHandler& O6 F+ G% |# X$ v( i* S' y4 O
  35.     {
    % k# I7 ~" [$ D: Q
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池$ {* B8 R  j1 m$ p1 l; @
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    - j8 _! i3 h( _5 v/ K6 C. [
  38.         public void ProcessRequest(HttpContext context)  d2 {' Y1 P7 m6 k( z5 ~2 F
  39.         {
    $ r$ H0 f  k2 J9 \
  40.             //context.Response.ContentType = "text/plain";
    ( G8 j0 X1 o. H" k0 W: N
  41.             //context.Response.Write("Hello World");
    - }$ T! S+ H" N$ D" o% H
  42.             if (context.IsWebSocketRequest)
    - F3 W8 _! A' e+ Y8 V4 j( O
  43.             {
    9 r- U0 L$ b( k2 n# |4 |8 n& d; S
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    & R( r8 P1 g! L  l2 p! V/ w
  45.             }
    $ \8 J6 l9 F) {: _- ~# \. w# N/ m
  46.         }
    + O4 \1 {$ P: J( ~2 u1 P

  47. 5 V1 e& k) ^" }" _7 M! R
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    1 c0 b3 O5 V* F& t7 y9 `( }
  49.         {- I5 t  ^, g# n( |. J+ g8 n- u
  50.             WebSocket socket = context.WebSocket;
    * ]% ^2 K! O# K
  51.             string user = context.QueryString["user"].ToString();! z5 J+ u. ~8 Y/ F' F6 j" P0 R' F

  52. 0 e3 b* e# C7 a3 f1 \
  53.             try* V7 J( A0 b3 J' M, F
  54.             {
    3 K# H+ D& z- n% G
  55.                 #region 用户添加连接池
    ) m- S$ K4 H* q& k1 W9 a
  56.                 //第一次open时,添加到连接池中
    6 N7 J8 H% i7 Y) L5 W
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    . r: ?$ _7 P/ Q5 C
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加0 w; p* o3 ^3 X) c% J* C" R0 r
  59.                 else* w+ \6 C/ _4 n  C
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新2 T3 {. W! W* a2 G
  61.                         CONNECT_POOL[user] = socket;. l0 {; a  C% n% t* z0 k
  62.                 #endregion  r2 O. y; D5 @. K' p/ Y

  63. ' W6 p: r9 ^9 W, @$ b
  64.                 #region 离线消息处理8 t* o. c4 I- L7 ], J; O% h9 O
  65.                 if (MESSAGE_POOL.ContainsKey(user))6 X  b9 r0 G* o1 G0 b+ c4 `! o3 E
  66.                 {4 W# r2 q% W2 {+ Q3 ?
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    " T1 u7 V1 _- ^- d
  68.                     foreach (MessageInfo item in msgs)7 O$ p) J, ^1 r( V
  69.                     {% V1 J& j/ e4 R
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    8 l, \  f' ^4 L/ c' q
  71.                     }
    2 ^, Z/ w* `! U8 W& H8 K
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    + ]4 B1 y# ^6 \
  73.                 }
    8 h( z2 W/ U+ R( y
  74.                 #endregion
    : [% {2 r% H/ ?* s( A1 ~0 V+ b

  75. ) t8 q& a; ^0 m1 U
  76.                 string descUser = string.Empty;//目的用户
    . Q" v! s) Z* n& u9 b
  77.                 while (true)7 b9 P4 ]8 T! U/ u" n
  78.                 {+ _8 d3 J! C8 G- L! j3 ~
  79.                     if (socket.State == WebSocketState.Open)/ |+ q1 O5 J, i0 V' V3 W# @4 O
  80.                     {' S% Y* V: V2 q# p- }8 b$ h( m/ E
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    4 D0 Z2 F2 K9 C) j, C/ V
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    ( q5 L6 X: @4 \, Y# X. m

  83. & Q: I! x# p6 {! r/ d9 D: ]
  84.                         #region 消息处理(字符截取、消息转发)2 |' B# K' D5 h/ r
  85.                         try) I' C2 h8 n/ P9 V: k. \
  86.                         {  B& S2 W5 q/ i' ]
  87.                             #region 关闭Socket处理,删除连接池
    7 e) H" C" a" O* ^# J
  88.                             if (socket.State != WebSocketState.Open)//连接关闭5 w4 X+ w3 B/ B) _: O) _9 V. ]- e
  89.                             {. J: f7 A6 V4 @! m. `& Z- V
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    0 l) T2 E; \8 r" J9 |2 V9 M& F
  91.                                 break;
    ' V+ }: B" m2 z% P
  92.                             }
    2 o8 R2 ?5 M: _- D0 Y
  93.                             #endregion. r" k9 r, h" K' S) ]8 X
  94. 7 P" h" Q7 K: M9 B  H# ~! c
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息3 z9 j7 @' _9 C- ?
  96.                             string[] msgList = userMsg.Split('|');2 Y  w; ~3 {1 ~5 `7 ?3 w8 Q
  97.                             if (msgList.Length == 2)7 a1 V6 k  L/ l
  98.                             {% l- G: E6 I* p: m1 p1 O1 G
  99.                                 if (msgList[0].Trim().Length > 0)0 c. ^6 S7 a5 K0 R# _
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户9 Z% U; a# e! P* @7 C
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    ' \8 c/ y* A" ?2 E
  102.                             }( t8 [7 R8 Y% r9 [
  103.                             else' g3 ~: c9 _1 J1 l3 a
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));& f! V4 E; j& L# {0 @, t) I4 Z' |

  105. - Z6 `) C0 l1 e1 x" ~$ }
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    ; r: h: V# ?0 x, ]1 s- x( J. Q
  107.                             {( I8 K+ V* M. ^5 K3 f6 g
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    * Y. |* A, a+ j0 E
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)7 }4 k8 h6 l8 |) |/ z9 Y: N+ I
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);0 U' z* }+ m2 r5 W" B
  111.                             }
    ; b' `' I' N& K  A. k- C% R  j! A
  112.                             else: }6 R7 ?- B1 D; h
  113.                             {+ j& @# ~8 W3 ~. Q( O2 D! x) i/ S
  114.                                 Task.Run(() =>2 G% l9 P# \3 H4 Z6 @
  115.                                 {4 L# o) G& n! R. g* H
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中( `- y% I% m5 k7 I# |. N
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());  u( a' K/ V  e. p( ~
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息5 u+ T2 U& G, Q) V2 M; d7 H7 A& S8 G
  119.                                 });
    8 L7 Y2 i1 N! T& U4 Q6 h
  120.                             }+ }+ D1 P" N! R
  121.                         }* v4 T+ i0 y" z
  122.                         catch (Exception exs)6 @% |8 X2 j) ?1 U
  123.                         {
    3 K/ L) p/ r9 _
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    ) ~; x" G" W& v. E0 I2 @: d; Y/ K+ s
  125.                         }
      j; T0 ^; x! }5 r" n, O
  126.                         #endregion
    / N9 I# R' `2 m9 v9 f( T
  127.                     }0 `( G; n  K. z2 y' h! a+ Q0 d
  128.                     else
    ) h$ R# o5 m/ R3 a9 @/ a
  129.                     {# s, R5 h# L5 H, d
  130.                         break;
    4 P8 j( D; [7 S* T/ f
  131.                     }
    0 t7 P$ t5 c' B' x2 s" d
  132.                 }//while end
    ( z. l) j8 }. Y( a; b
  133.             }! A6 Z2 m. I, u8 W
  134.             catch (Exception ex)
    # q/ S, v: h, f* C  b, M* l) k
  135.             {
    7 H  {$ T- n& P2 C
  136.                 //整体异常处理
    9 v0 h+ Y  h6 e- j, j( F
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);; a+ a% D7 }2 G
  138.             }# h$ Q1 {  V! s8 A% R
  139.         }
    1 {3 g) H+ ?# J* G: Y5 z

  140. & d8 s* [+ B7 Y0 F5 n- c% p

  141. 0 k0 g9 T3 ~9 S
  142.         public bool IsReusable2 H9 F4 t; O  K( w- V
  143.         {
    9 a# Y7 f7 ^6 D5 U: ~; r
  144.             get. K& e( B5 K8 D
  145.             {  G  Y2 U+ m! v9 G- f. p
  146.                 return false;7 ^6 W/ A, S# R, R& p: K
  147.             }
    3 h- ~+ `% z" h6 j+ A* T7 L
  148.         }* u, \8 J  \# v; _2 K
  149.     }
    * s" _9 H: S9 T
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

# d1 a7 a* L9 n- E, I4 {8 G1 c6 Z
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-6-20 01:18 , Processed in 0.060983 second(s), 22 queries .

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