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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

3 k* \0 m- p9 P+ M
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    9 Q% q, v) k) f6 B# K
  2. using System.Collections.Generic;5 [( H: b9 c& U- l6 {% e& b
  3. using System.Linq;
    6 g* `1 \. k" r& X9 M; u, e; O
  4. using System.Net.WebSockets;
    . K7 N6 F$ O  P6 X) m4 L* b
  5. using System.Text;
    # N# G- e9 U& {/ C) Q
  6. using System.Threading;
    1 B, J" ]& `7 G' t
  7. using System.Threading.Tasks;
    9 |( G/ ^) r4 j0 S' ]5 X: ~$ G/ p$ ~
  8. using System.Web;) d- y( R# G! H( B$ V
  9. using System.Web.WebSockets;
    0 Q& w# S( e* o. ?

  10. ! v0 ]( H; E. f& M

  11. , [8 `# |4 `" j, A8 ?$ D
  12. namespace WebApplicationWebsocketHandler. Y. h8 s/ {- V7 R) {6 `- j
  13. {$ ~2 {& Q, L' U( R4 \
  14.     /// <summary>2 x1 M( o. P) e9 D
  15.     /// 离线消息- S1 D7 G- b$ l( ?
  16.     /// </summary>
      N* N8 v: p+ }6 |4 Y$ e/ v2 [$ i
  17.     public class MessageInfo0 _$ ?2 N$ {- _( L# e; n. y/ E4 M7 w( I
  18.     {
    * J& x$ y/ c. n# x3 |$ l  }/ D
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)' F% ?8 Q/ P& q5 ?" D! ]" x
  20.         {
    ( ^8 h$ d/ `( s( b0 h
  21.             MsgTime = _MsgTime;6 A6 j) S7 l; K0 V4 b  n
  22.             MsgContent = _MsgContent;
    ) K' }; R8 K3 ]
  23.         }) Y+ i  U6 i4 S  W4 d  ?$ n
  24.         public DateTime MsgTime { get; set; }9 `& d! C. {* R
  25.         public ArraySegment<byte> MsgContent { get; set; }7 _, Z9 O6 q, p2 e+ v9 U( y
  26.     }
    $ H# U1 p" @  [# r! a
  27. ' h7 m, k+ m; }( \
  28.   W' f+ w+ ]3 q* a

  29. ) g& r9 A9 A. Q* j

  30. ' L2 h0 L: ~' M9 F9 C3 T& l$ t+ q
  31.     /// <summary>3 Y% c& [$ H2 @% c" n
  32.     /// Handler1 的摘要说明
    " m: i) T3 D- K& F) N: x# m
  33.     /// </summary>
    4 k( U/ |- }8 {
  34.     public class Handler1 : IHttpHandler* t3 |2 E6 x1 F: `' @
  35.     {
    ) x" }- p; Q6 k- Y5 B% Q& g, ?
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池" s" ~; B# H2 [6 P! X' x
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池; ]( R) g7 j% I2 M* v3 r$ E0 W% j
  38.         public void ProcessRequest(HttpContext context)
    ( t1 s3 L" V1 v  m
  39.         {
    - l, X! y0 _. _% Y. D$ w# ]
  40.             //context.Response.ContentType = "text/plain";
    % @7 Y. f' \* W+ M% M8 U
  41.             //context.Response.Write("Hello World");
    ' M: F) v+ S* y3 U  F: h
  42.             if (context.IsWebSocketRequest)% B* u! `, E) A6 g
  43.             {! \; a' r# x! ^$ I, |) g3 L. U
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    & A! P/ m. j+ L8 R
  45.             } 3 x/ S, N9 m  I. n# o: H
  46.         }
    " t. `1 {1 O$ Y0 F

  47. ) j1 e( H# O& W# H
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    * J5 J( s- `1 F# ]! p$ ~9 j! @7 G
  49.         {
    - @1 |$ a  X$ Y: I8 ~* |
  50.             WebSocket socket = context.WebSocket;
    9 G" l3 \9 o0 `/ W0 n; Z
  51.             string user = context.QueryString["user"].ToString();& M" t, S! k' X
  52. 1 |" L/ Y, B! Y1 W) q
  53.             try/ l& h0 w7 n7 [& e& s2 x* ]
  54.             {: q* s4 i! M0 Q+ p0 m
  55.                 #region 用户添加连接池/ `9 }  e8 K2 q4 @3 B, O9 I5 c* ^
  56.                 //第一次open时,添加到连接池中
    & U6 Q2 y. u: V% @& b
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    6 x" F' A& N% E
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    1 G! }4 I7 d; m
  59.                 else
    6 e: E4 B# F* K
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    8 z4 `9 U) d" K4 }
  61.                         CONNECT_POOL[user] = socket;0 y, ^& b/ m2 {
  62.                 #endregion3 U6 A; k4 d3 h4 K
  63. ' d. D+ v8 o6 }) f& l
  64.                 #region 离线消息处理
    . `' T5 h+ B) J0 I4 i, P6 C
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    2 [3 O$ `1 X+ o$ K4 O5 y) }' r
  66.                 {' K/ a' ^# w  I: \! g9 B; N$ U" {
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    & L# J  M3 {  e
  68.                     foreach (MessageInfo item in msgs)) ~9 }& K- @& f3 u$ H1 ^
  69.                     {1 P% Y+ l: H* }0 r. i# C: R
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);* ~! p, I9 R% x: Y! Q
  71.                     }
    % M. p6 \$ j/ A/ T
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    ! w" S/ |9 [' B6 m+ ?; W( }
  73.                 }% n; k' d5 C+ }4 q
  74.                 #endregion2 v1 q2 m# Z" _/ ]6 D

  75. & k: a  u3 X& H( @7 U7 V
  76.                 string descUser = string.Empty;//目的用户
    * z0 ]; m6 n) k( X4 p) ~# [+ Z0 G
  77.                 while (true)8 R$ W/ u) u  U$ m
  78.                 {
    , [3 `/ E) o5 a* m: R' Z4 d) a
  79.                     if (socket.State == WebSocketState.Open)
    , u  v7 S+ Z8 V0 @% p4 E% C  U
  80.                     {
    3 M$ Q! h  b+ J7 `# n7 ~
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    " k, Q8 y, p! Z! \
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    2 I% G0 {" Y. c! i; W! T( a1 X9 X
  83. + T! c7 K  D  Z+ ?6 ^# j
  84.                         #region 消息处理(字符截取、消息转发)6 V9 v5 P* T  l
  85.                         try4 |' y! K0 n4 z" g
  86.                         {5 H" |% t$ v& L: ?
  87.                             #region 关闭Socket处理,删除连接池
    6 j- h  q6 |  }  _7 {0 h8 A
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    : b9 C  W, u$ O9 Y& A
  89.                             {2 D3 b3 C& G& S# h# |
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池' @! I/ H; p! s5 \( f/ A5 T
  91.                                 break;0 Q0 U6 \+ f( G) A) c
  92.                             }6 a, g( c& h  R2 b( i1 j
  93.                             #endregion  H! {+ U8 Y/ {; [' J- h$ L+ J
  94. # H: c" w$ q9 u& h7 a' ~/ O/ \( j
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    , m! j! k" m9 V' h- M& W! O  P
  96.                             string[] msgList = userMsg.Split('|');
    - [0 r2 n' Z/ v, O% O( s
  97.                             if (msgList.Length == 2)
    # W+ O5 A5 t% `* ~- ?
  98.                             {/ C, b0 M1 O9 R
  99.                                 if (msgList[0].Trim().Length > 0)- G- ^6 b6 }& P  i9 c( R" C# J
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户/ J" W2 t' K/ F
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    6 {; n5 R4 a; i+ U6 m. U( P
  102.                             }
    * s% W* _8 @5 U  P! z
  103.                             else0 m& d5 y4 a) L9 c$ u& A
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));" H: t" {  T  J5 B% v9 ?* f

  105. : x* M% Q/ M/ c; T' x
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线5 x: z+ U5 S5 [
  107.                             {$ t+ `8 B. u/ e
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端7 U( ~7 C) P$ ~- r9 q( Z2 ^
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)5 l9 D; V3 G2 S: |- r: O% B9 g1 U
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);8 M5 ~! W5 t2 G" O3 a
  111.                             }" c. G! M4 q6 Y( T( C1 u+ y
  112.                             else
    : f: J3 s0 Q: r! c
  113.                             {5 h# l. C( m9 X( s
  114.                                 Task.Run(() =>; `: K! N2 u) p( A
  115.                                 {0 E. i' }# |: o
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中% h  t% g- Y9 P% n) j$ u
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());$ `$ q5 c+ Y8 _  G3 Q; M% D5 r. f
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息" }8 r- g: S- K4 q+ U
  119.                                 });" ^0 p6 X8 r' t, ~: m5 H, c* S
  120.                             }7 r* ~% C5 G5 Z" F6 Z
  121.                         }
    0 [* I7 }: L8 U# W+ l" M7 s0 R5 h
  122.                         catch (Exception exs)
    6 t- v7 {' [6 k8 ^, m
  123.                         {" d1 U3 E+ ~/ J7 j0 o4 }
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    ( @3 m1 ?2 U4 _9 g( d
  125.                         }' i( U, I) v) M. y0 l% p% O$ c/ V6 N
  126.                         #endregion: h! G$ ]: n# d. H8 ^
  127.                     }8 W0 o. ^! K9 B% ~- |
  128.                     else( t) H1 R; [6 {  S( h& L( X& L0 i
  129.                     {
    $ H4 M7 o2 t6 e
  130.                         break;" L* I7 X; b4 C. a1 X
  131.                     }, d6 ~8 P* W# J' s. |* E
  132.                 }//while end. H0 w" b9 L- M2 M; Y( t
  133.             }5 e; h& S' b( c3 Y$ `  `
  134.             catch (Exception ex)
    " ~2 K- y" P( u3 G9 w
  135.             {
    5 w1 h! t3 }& \% g  M# G
  136.                 //整体异常处理
    9 z& V: Q) f8 N; y5 s: M2 R9 a8 u
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    . W- U. s! {6 Y1 Y; I
  138.             }; X% ?8 h8 |  D3 A  n% N
  139.         }, u# {1 [2 E9 X: J# B& A5 D

  140. 9 ?' C" C2 v1 }. ?$ C# D

  141. 6 B% A1 {, A1 c
  142.         public bool IsReusable6 Q7 y9 `  e* l; D" C+ |# f
  143.         {4 L7 b7 r; g. p+ o
  144.             get
    / {8 o. d& M0 }$ P) k, N3 l; l
  145.             {
    3 i. y. ^& \! u0 A. y; c
  146.                 return false;
    % x4 U1 H$ T; W; M% D% K
  147.             }& ~9 W  s7 \- H1 B4 Z* H
  148.         }3 s: r1 F0 e. r+ K# Y
  149.     }
    ) n: ~5 Z; o1 P$ ?* O$ O9 N1 A
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

3 w% G4 X( Q/ T  j
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-4-30 20:48 , Processed in 0.061398 second(s), 22 queries .

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