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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
: G/ o; e2 l' n' _  t0 ?, V9 o
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    3 c& S3 c" K$ i. T) f
  2. using System.Collections.Generic;
    ; Q# F- s$ I) V6 W' Y
  3. using System.Linq;/ d1 \& U6 R: r+ i
  4. using System.Net.WebSockets;
    % M, H" G( J0 h5 ?
  5. using System.Text;- g0 {( t4 X8 I; H3 F7 c
  6. using System.Threading;# q2 D' @' h5 j+ t( j0 G) _
  7. using System.Threading.Tasks;
    # b  l5 c$ r) ~6 `& k
  8. using System.Web;
    + l' n: f" Z0 i& v+ M6 A
  9. using System.Web.WebSockets;
    0 b8 S4 M$ C( \% P3 m
  10. ; H) g# C! X. P+ O

  11. # y. C& i' {4 z
  12. namespace WebApplicationWebsocketHandler$ S0 I2 L+ H! x/ F3 z
  13. {
    # h% O1 b4 j0 j
  14.     /// <summary>7 h* T) r: M3 o4 A. o" n1 [6 y
  15.     /// 离线消息
    ' R; [2 K( d! r
  16.     /// </summary>
    8 B1 Y" j5 b, B2 u- S
  17.     public class MessageInfo
    + \7 w. u7 L( c5 c$ D5 X
  18.     {& L* H( A4 R2 M/ B$ M
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    4 J; C: C  N' \. t4 B# ?
  20.         {
    % {8 L6 t: S% @: {5 n# _
  21.             MsgTime = _MsgTime;
      V, x: h- U  b; X" K: L
  22.             MsgContent = _MsgContent;
    , p4 ~, r2 T; t! ~
  23.         }
    ) F! S* r7 V0 `* c5 N2 }0 C
  24.         public DateTime MsgTime { get; set; }3 G( B/ a- ~# T
  25.         public ArraySegment<byte> MsgContent { get; set; }; P+ A  D8 V% g- m
  26.     }
    0 A( B5 x/ L# z& G' h

  27. ) U* V$ [/ H# \: w/ \/ V
  28. . V* p7 C% K, {! C% Q( {  f
  29. % y" Y7 W# k- u+ {

  30. ' G1 I  I+ q" W7 }# `# d# @$ a' w
  31.     /// <summary>* Z/ s8 ?! U0 w. L9 i
  32.     /// Handler1 的摘要说明
    . C3 H0 I7 Z7 Z' v. g4 `
  33.     /// </summary>+ w8 s; s' J; h. N9 Q! P
  34.     public class Handler1 : IHttpHandler3 G) s1 E% i0 k2 i, n5 j
  35.     {8 J8 ]! o  X5 T4 ]) N) ^" V' _: F
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    ! o3 c% t+ e' a  U
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    ( W5 N; a6 {7 e# s" E5 ?2 \
  38.         public void ProcessRequest(HttpContext context)
    / v$ e! j- D. ~
  39.         {
    : I7 F; x# E2 e4 k2 X9 t  @3 ]
  40.             //context.Response.ContentType = "text/plain";8 h$ H, Z7 X' W9 ~! E
  41.             //context.Response.Write("Hello World");+ D% u  D' Q2 S& E( i
  42.             if (context.IsWebSocketRequest)) T1 x8 w% k% N* ?
  43.             {% H) ~$ c# ], D/ N
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    : r, v7 W  b3 U3 D3 w% O8 S, }
  45.             }
    2 n) P% c6 ~: e* q; y! d+ Z' k
  46.         }
    ' n! R  `4 D' g5 {# F: u

  47. " V# p+ w- O  {
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    / u/ D0 I+ z$ i/ f$ }7 s1 P  ~
  49.         {
    5 g. I. I* P" r7 _) U5 e. t2 [0 @
  50.             WebSocket socket = context.WebSocket;
    9 e7 @# b* P; D) G0 b  V
  51.             string user = context.QueryString["user"].ToString();  r4 R7 z) _0 W& G- O8 e
  52. & ?8 L0 [( ?$ h
  53.             try
    & v9 b/ q: {1 `# Y/ f& L3 z
  54.             {
    . \' w8 ?! w% R6 r' c
  55.                 #region 用户添加连接池
    6 i# q+ _! b. R' R% f
  56.                 //第一次open时,添加到连接池中/ q' B) Y# r& R- e
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    2 y8 Z: s; `! J, g
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加3 c: O8 U- ~+ n, \$ A8 `* U/ W
  59.                 else: O1 Q0 a( Y9 @& n# ^+ z/ {
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    / [# a. l! X( ~: p
  61.                         CONNECT_POOL[user] = socket;
    ' a0 D- c7 }; t4 }6 h
  62.                 #endregion
      t7 ~# X- r8 ?7 k+ I9 V+ n. _
  63. " Q" H  W* }: r0 W( W% u# e
  64.                 #region 离线消息处理
    3 q$ X5 h( P5 N% w
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    3 ?( Q9 w& s5 f" K1 f
  66.                 {
    / q9 m7 P9 y2 P) s" w5 p. @( \
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    . M7 Y, ~! D% o+ v1 U" @, c
  68.                     foreach (MessageInfo item in msgs)
    1 d) T. P3 L7 ?1 n/ k' F7 ?- b' r" S
  69.                     {# ]" x7 f+ G: u& c( u3 @% {
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);0 @6 G/ W" G' \! p. t5 P- c; e2 F
  71.                     }
    4 o: P* C( T" Z
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息! s# @) h9 H  A0 @  E4 }
  73.                 }
    2 A! o. }* f5 J2 q0 M
  74.                 #endregion2 L$ p' c$ s; h$ ~3 Z

  75. 8 f4 b/ Z' p3 \% ]  i& ~; s" i5 ^4 ?2 [
  76.                 string descUser = string.Empty;//目的用户
    ( d( Q7 @$ ~& s: V
  77.                 while (true)1 ^# ]8 }/ X, S) W6 N0 O8 N
  78.                 {5 e# a" w9 Q: O
  79.                     if (socket.State == WebSocketState.Open)
    1 S) R6 o5 s' P) I  J8 @
  80.                     {
    ; o2 x9 P- h( i% n
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);! K1 \, ^% r. G0 |
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);' w9 {/ p. g0 y. M0 `5 k
  83. - r) u8 _5 Q3 |- E
  84.                         #region 消息处理(字符截取、消息转发)! p  S$ U9 c# _* ~
  85.                         try1 Z& o3 m+ ^9 `# B' E/ V
  86.                         {+ |, \1 N4 Z/ i! |' m9 @
  87.                             #region 关闭Socket处理,删除连接池3 Z/ ?- F% \+ U$ n
  88.                             if (socket.State != WebSocketState.Open)//连接关闭6 n2 |5 ]  K  K& M* H- G
  89.                             {
    2 Y- D6 q: X$ G9 p0 q3 `7 {2 u3 G
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池/ ^7 \, {" b2 v* R; l' E  ]- f
  91.                                 break;
    5 c/ u" |$ i- B. r2 q: g/ f- z
  92.                             }# k( Q- y8 z- p9 d9 R& p) k& J
  93.                             #endregion5 T8 w0 L7 L: H  D

  94. % c4 L5 h8 Q1 F; X" q
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息+ c1 q1 x2 G, N- Q
  96.                             string[] msgList = userMsg.Split('|');
    ; e' y3 V( V8 t8 k
  97.                             if (msgList.Length == 2)
    8 [& u0 n* l( }; G, j) {
  98.                             {. c: u! t) p+ Y/ g+ x
  99.                                 if (msgList[0].Trim().Length > 0)
    # X; O/ k/ R7 R9 S) e4 i
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户! I6 g* q, M4 Q) j" h6 S
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    - ~+ j. M; f. g. ?; l
  102.                             }, Q6 W7 C$ ~$ N6 @( a4 \( K
  103.                             else
    $ I9 _# q* M$ u7 a
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    ! e: \& x1 {' P, l7 d+ R# c$ I9 v

  105. 1 q7 I& S+ d) \# S& Q
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    8 m1 W' |& _' z: u/ e! t
  107.                             {
    1 I! R3 K1 Z% B1 r% K! T* W
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端/ S" m$ E4 _3 X
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    9 P% s# D# N+ l6 `0 Y
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);( _& \+ H! Q( Q; E+ P1 s7 w
  111.                             }+ n: h  x* L" Y
  112.                             else
    / P* e' T+ @0 g3 n
  113.                             {
    5 z" g, v8 ]7 p: c* ], z
  114.                                 Task.Run(() =>: y3 Z" P3 y$ }8 Y& @' |6 o* i
  115.                                 {
    7 y. M4 q! k9 L) ~) w/ q9 k
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中  j7 b5 l5 X; |' p, X: m
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());, l# n7 L) b! w0 P) {9 O. Z
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息, r! n+ B  {/ M3 U
  119.                                 });
    3 @6 v. ^9 U: J
  120.                             }
    2 c/ X/ {2 m, ?' G1 c
  121.                         }7 z; F8 p* E$ p5 ?! X: Z
  122.                         catch (Exception exs)( U6 g$ F8 S0 D' Q
  123.                         {
    0 \, a# H9 w4 s( x1 M
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    4 L1 v& D% J) d1 Z& D( P# Q
  125.                         }
    8 @& S) W5 X6 o% M8 j$ d5 m
  126.                         #endregion- t! J# `. G% ~& D# ?
  127.                     }
      k, v$ P) t0 t+ o/ T: Y
  128.                     else( D5 q8 F0 J; |" K& ~) q4 h
  129.                     {8 W& f: m$ l" G* H$ ]# l: \
  130.                         break;
    $ e+ G% U3 T+ z2 s
  131.                     }
    " h. V7 h5 @0 {1 B8 ]/ R
  132.                 }//while end
    # E+ H/ p" U6 e" U- g3 _
  133.             }
    " f+ c& K( w& \. k& d8 \2 ~
  134.             catch (Exception ex)
    1 y$ H  ~2 h" z3 f0 ^) P
  135.             {
    , p4 Q' t6 ?* _. n% W
  136.                 //整体异常处理! W& v) }$ g$ `& k$ J) r
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);' R4 M9 x( l/ V; ?# L
  138.             }$ L$ |( F! x% G9 x& s& l3 I
  139.         }
    " ~5 B5 W# @  l2 j; p+ }

  140. ! ?5 c- W7 X' D

  141. , w0 f: |- m  J+ s6 Y, B0 M$ v
  142.         public bool IsReusable
    2 A, z: U+ i/ Y1 A9 U9 q( b
  143.         {/ L8 h* K; a. T' S0 Z' m
  144.             get
    + o! l1 A4 V/ ^4 ~4 [( m; a! k
  145.             {
    : O# y6 {" o' A* w; B8 H) |
  146.                 return false;' O5 {# R0 O) R  Q7 v, C5 S
  147.             }
    & f$ O& q* E+ k% t% y; ~
  148.         }/ G' F5 R) t; |! M$ i
  149.     }+ b$ ?6 B) [7 S. f6 O6 A
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

) N) k3 ]% u% M/ |5 e
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-6-26 09:47 , Processed in 0.161923 second(s), 22 queries .

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