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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
/ p6 e$ S' `: ^
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;: j  R+ }& W" j
  2. using System.Collections.Generic;1 Z/ C# L( N9 F2 ^% m) k' a( ]
  3. using System.Linq;
    . w0 `9 ~  Y3 a
  4. using System.Net.WebSockets;% |9 M9 r2 F3 N! m6 ?( d. G
  5. using System.Text;
    + m; H9 u1 K$ c! U" T6 y
  6. using System.Threading;5 @/ X: R; b& h: k* ]# ~4 l
  7. using System.Threading.Tasks;
    ! W/ y7 K) A% o5 R2 A& c( i& {# k6 ^
  8. using System.Web;
    ) m0 X- ]2 ?$ d' ~0 E8 {
  9. using System.Web.WebSockets;( Z8 h" l6 O0 w5 u

  10. 4 L" L- ]7 g! S
  11. 5 f7 |) g2 u- Z3 i* h, D
  12. namespace WebApplicationWebsocketHandler
    / W  x+ `" c0 W1 z
  13. {" U7 a7 g7 x( D9 |! o9 _6 u8 g4 M$ U
  14.     /// <summary>
      h/ a! c6 b) w6 Y* g" o) j
  15.     /// 离线消息7 t' H$ _( j9 Y" x/ ^  c( V8 U
  16.     /// </summary>- Y0 f( Z2 [/ M6 G# h
  17.     public class MessageInfo
    # z' M  s1 e. E# f& P2 a* v- A  `) z
  18.     {
      v, R" U+ d0 |+ t% H
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)! Z$ U9 u- W$ B' v( ]/ `4 \: j* E
  20.         {
      s$ _9 |) [) V# Z9 H8 p$ R# l
  21.             MsgTime = _MsgTime;
    " ]: `, T* }2 u- Q/ A; Z9 `. H
  22.             MsgContent = _MsgContent;% H. _  K& Q! o7 b! D" d: l
  23.         }
    ) E9 E  D* n6 k0 S  i( N
  24.         public DateTime MsgTime { get; set; }5 o1 _" g7 m, e; A  k' v
  25.         public ArraySegment<byte> MsgContent { get; set; }9 n" Y0 k9 H: N8 k
  26.     }
    6 T. w5 j2 Q  C6 l, u

  27.   Q: m9 P. e; j1 x' q
  28. 2 p2 U: X+ H) b- H
  29. $ T/ }# d3 ^2 J, c

  30. " [  p2 y& q5 Q- _3 o4 n. r
  31.     /// <summary>
    & \8 X+ A- n' H% K$ S. ^
  32.     /// Handler1 的摘要说明
    " A3 h7 Q- A5 x, P. q' C9 ?
  33.     /// </summary>
    1 u5 v9 A0 ^: S: V6 Y$ y& X
  34.     public class Handler1 : IHttpHandler
    ( v1 o2 \) b9 ^0 E, |6 D4 ~; `
  35.     {
    3 b: e7 i. z% l) F- U! C
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    # k5 h) ?3 _& B
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池1 K8 e6 G5 m) L1 g, E/ d! ?
  38.         public void ProcessRequest(HttpContext context)* ~5 t. o0 ~- r# f% m
  39.         {, ^, W9 x8 y( k6 g; Y1 v" z. x7 T
  40.             //context.Response.ContentType = "text/plain";2 c( v0 ~' ^; S' m$ W. O! c
  41.             //context.Response.Write("Hello World");
    " \1 D+ {/ R' z, I, d; @5 v
  42.             if (context.IsWebSocketRequest)
    , ?: m: h* D& O  y/ C
  43.             {
    # G( C7 u- P' H( d' S4 C
  44.                 context.AcceptWebSocketRequest(ProcessChat);6 Z- `- y' t" h9 J2 }( x
  45.             }
    3 W, T. k6 y  e- V3 V; _; G: g
  46.         }3 h2 y" \  ^" F/ j) d

  47. . X- Z! ~# r/ w7 [' G5 m
  48.         private async Task ProcessChat(AspNetWebSocketContext context)* }& X9 h: b6 y% q9 K
  49.         {; ~5 W1 D9 |9 G( Y) K! x5 u# S* O$ v
  50.             WebSocket socket = context.WebSocket;
    $ b# Q/ w& u9 G* z
  51.             string user = context.QueryString["user"].ToString();
    , F2 d' E/ X6 o7 \6 X

  52. 7 u! u" O! \# `
  53.             try
    . j  V6 J2 y: r  z
  54.             {
    ) d2 f' Q8 g+ A# W6 D# @
  55.                 #region 用户添加连接池% q+ s' z: O* t, S# C
  56.                 //第一次open时,添加到连接池中
    # H3 }, [8 w" J/ N. K$ G: l
  57.                 if (!CONNECT_POOL.ContainsKey(user))0 j  Q: q* h: c; J8 G: h0 q  u; l
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    # J6 _+ \& |. }2 m
  59.                 else, G0 K! B  M3 d: ^# M% X, c' }
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新, N, j2 V  B- E  {. `
  61.                         CONNECT_POOL[user] = socket;
      O) V5 U9 z1 r) L" A: @
  62.                 #endregion
    . w/ Y1 Q7 x& P- e

  63.   r! W1 U2 E: L4 Q! ]0 I" d
  64.                 #region 离线消息处理$ v; Z7 J/ A7 ^! d5 Y
  65.                 if (MESSAGE_POOL.ContainsKey(user)), P4 {8 q/ h8 v" [
  66.                 {, q7 h( [, t$ B  w
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    ( R% V+ h/ X2 x0 J3 r' b
  68.                     foreach (MessageInfo item in msgs)
    0 n# _- X; [$ ]
  69.                     {
    ) r; r! s, W( L  {+ F1 N+ I' ?
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    " h0 \6 l/ b9 R; D4 s0 t- ]0 _
  71.                     }
    7 A  s& i4 g; q0 O; h# s" m- \
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息, o3 M% ~5 N5 N
  73.                 }5 [) Z4 i8 D& v$ ^
  74.                 #endregion6 X( P3 M1 D# Y9 D6 P

  75. 3 |5 a/ ?2 n) @  |* N# p
  76.                 string descUser = string.Empty;//目的用户) s6 N+ \- a$ b8 c, J
  77.                 while (true). q9 o0 f6 q7 D& x3 T; g# a
  78.                 {0 d7 B4 l/ C9 e6 e1 a& K
  79.                     if (socket.State == WebSocketState.Open)
    7 B0 B: f% [, d0 T3 X
  80.                     {7 P: o0 g3 E2 W) V0 [- R
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);/ w7 k1 G) q* @5 }+ M/ o0 E
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);9 z9 Y, ^5 f7 R
  83. : p# p  i- ?: b  M6 ?+ H, h( \
  84.                         #region 消息处理(字符截取、消息转发)
    / ~7 e- z8 q' L( ~+ j) X2 F
  85.                         try; a* g+ C2 B/ ]$ C" Y% p! Y: `
  86.                         {" L% Y- }" U- c9 P7 y/ X6 J
  87.                             #region 关闭Socket处理,删除连接池8 {8 T( T! o3 q  l
  88.                             if (socket.State != WebSocketState.Open)//连接关闭0 x( X4 q4 q* j2 l3 }: t  |7 q
  89.                             {
    0 G7 @3 P& E3 w& H' m
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池3 Y1 N+ t. n% f3 l6 x" ?
  91.                                 break;
    ' R$ t- N  V8 M5 k5 ~9 q  H
  92.                             }: d9 g5 c* g2 X
  93.                             #endregion
    % x# q- a8 y( ^( p. O
  94. $ S4 z4 E& w1 [" X7 f$ r' Q1 Z
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息- j3 P, |& e6 ?: r; ^
  96.                             string[] msgList = userMsg.Split('|');
    % k! M' I' h: c
  97.                             if (msgList.Length == 2)
    ! v6 N: y+ M  u& S  D
  98.                             {
    ! q' ?. J  h8 i5 s
  99.                                 if (msgList[0].Trim().Length > 0)! z3 r+ L+ t/ P6 M; }- x- ~' ~2 n$ G
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    # C4 p& ?; L) o. B# P
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    $ w3 W5 Z! T- J6 f- q( Q
  102.                             }% }: U1 I' Q1 G$ J, C3 \( ~/ E
  103.                             else# W4 q+ ]9 Y  f/ ^4 Q' M
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    5 i# e7 s( q6 J7 `0 N* h8 I

  105. : W! ^( \6 J2 |" |; Q, \
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线1 \  p! W* |5 B9 Q; s4 W2 V
  107.                             {* v1 i- l; T% [$ ]' l: _8 h" i
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    + L0 ~5 d0 g; V" r3 O
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)  K+ }4 N, O) d
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);1 f+ D* q7 z& x( a" T( e% y$ i7 @
  111.                             }
    9 Q; g1 W5 B2 p+ k; C
  112.                             else3 n# c: n2 F" m  n, F/ s5 ^) C7 m
  113.                             {+ V, K5 g8 }( f  D) s' s0 l
  114.                                 Task.Run(() =>3 J$ _: Z6 w: t# w
  115.                                 {; K3 D5 x0 _/ C1 L' H) {8 N( k. L3 L; v
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    & i. I7 K, n/ @; x1 S2 V! [
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());% r3 I1 V1 D8 r, O
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息/ F8 ?, t# f% X5 F7 B
  119.                                 });$ E5 J7 S2 J* L; g: B! P
  120.                             }' I/ W$ m  C! |8 P
  121.                         }
    7 d4 C( e' O% W
  122.                         catch (Exception exs)/ H  \2 b$ B% q0 A. H
  123.                         {! x$ p) g7 ?5 Q. z2 Z6 c
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    - _8 k( j- u# g' Y4 \# {$ |
  125.                         }0 u& U: q7 q9 P* N
  126.                         #endregion$ r0 c: O, _, t) M
  127.                     }
    ( f  f8 j5 k9 W! x' P
  128.                     else
    # x* p  Q- i  H- e8 w2 `$ Q) f
  129.                     {
    , `! U7 G5 a: b8 D$ B$ V' a
  130.                         break;
    4 {9 C$ K# J  S' N
  131.                     }; e: a% Z3 t, ?" @6 H2 d# u
  132.                 }//while end
    + C& `% \' O6 E; J! V6 y. z9 j$ X6 j
  133.             }
    1 d# b' P6 z% {1 T. }; k* j
  134.             catch (Exception ex)
    " [- @, l2 t" r
  135.             {/ A7 Y0 j$ C$ V7 i. d/ g
  136.                 //整体异常处理( ~/ S1 \/ G+ n" u) k" X4 K! I0 }
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    . c% \2 W; Q/ q9 ]! _- ~# D# v
  138.             }" F0 t$ z+ k9 Y% @" v
  139.         }' H4 G- e* ^! t9 x* P# |

  140. 9 w' k* y8 K" e' u

  141. . K$ T6 s  D4 `$ y
  142.         public bool IsReusable8 t  ]( S7 ?0 Z$ K$ s* q6 c5 D! Q
  143.         {
    ( P/ ^' a2 y& a6 x' M+ C4 n
  144.             get
    9 j* M, S) @% b5 O) }. ^
  145.             {
    0 Q" H0 [8 S7 ~( m8 X2 Y' ^
  146.                 return false;
    . T5 p0 D, o' v5 p7 S: z
  147.             }  j, s3 j: P# W" J# @
  148.         }
    ' O) j0 N/ m7 _- |  r! c1 J
  149.     }; D% z1 s' N& J4 a
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

% T) o, R3 P% ]  P& x
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-17 13:15 , Processed in 0.143916 second(s), 24 queries .

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