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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |正序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
& K- S+ Z3 b9 ]) U( _* e
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;# w$ q3 h  W: H- d- |
  2. using System.Collections.Generic;
    1 q. d- m( [1 T" M  X3 X$ f! [
  3. using System.Linq;( }" F4 E5 K2 N/ ~7 a
  4. using System.Net.WebSockets;
    - D. J* m, D+ e, O3 u
  5. using System.Text;; q) R3 w/ S5 n+ w, t4 h5 x2 p
  6. using System.Threading;$ T8 @+ L9 ^& z8 K' \& @+ Q+ p
  7. using System.Threading.Tasks;4 P( o) H- @# F: Y% T4 v
  8. using System.Web;" S! K1 _& s. c, _0 `2 u
  9. using System.Web.WebSockets;+ U( y) `* |1 l' Z
  10. - u9 s3 Y: |2 P  W. O5 S! F; t5 C9 \

  11. 8 K; n8 H5 C$ Z1 v7 |6 H5 R( b
  12. namespace WebApplicationWebsocketHandler
    & m+ Y2 V3 X9 Q2 F% Q& @
  13. {0 V4 E- L4 s; h0 H% F0 _& {
  14.     /// <summary>
      w4 @' ~; n7 m1 q& p
  15.     /// 离线消息
    $ N. B5 ^/ j$ U' y
  16.     /// </summary>
    * s7 Q8 F& c$ Y8 A
  17.     public class MessageInfo
    ( B' X6 Q  T  I# n. G2 P( V) u
  18.     {
    % t5 i( J7 J$ m
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    3 c- P7 K1 d- }+ H
  20.         {5 _( s1 m. l& f# S; t
  21.             MsgTime = _MsgTime;$ K3 G0 s6 u- m* E
  22.             MsgContent = _MsgContent;
    7 E- x! B- m8 |/ O0 g2 l- p
  23.         }
    ; u( q8 X3 e8 O2 h; _, X% L6 P
  24.         public DateTime MsgTime { get; set; }0 ~3 @: B; g! B, u
  25.         public ArraySegment<byte> MsgContent { get; set; }
    + a. @7 S/ {1 T0 |# w: n& g
  26.     }; r+ C1 D) @7 x+ g2 c

  27. 3 e% v& @, O: s
  28. 0 {: v7 d5 f& Z' x- F5 m6 o
  29. 7 e! F! L6 Z+ w

  30. $ O( u1 P5 _0 `+ c1 K9 P
  31.     /// <summary>& r2 ?3 [+ T3 Y- p
  32.     /// Handler1 的摘要说明) m, U& j; F% a. W, I' {
  33.     /// </summary>  h2 u9 ^; `' U" b1 y. N
  34.     public class Handler1 : IHttpHandler; y' b9 U7 k, O( }% l, E* b
  35.     {
    - v: _& B5 Z& i2 E6 M; b
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    6 v+ A' [1 o9 g
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    ( X  ]( J$ P7 ?
  38.         public void ProcessRequest(HttpContext context)
      V+ G; u2 J1 a9 x# o
  39.         {
    $ ~4 _* K8 a+ A, K
  40.             //context.Response.ContentType = "text/plain";
    + E/ f/ A$ k0 h4 L/ l7 y3 x2 c
  41.             //context.Response.Write("Hello World");
    : z5 _5 I/ L, s( ]- G4 D* l
  42.             if (context.IsWebSocketRequest); r, p7 P% B" N
  43.             {
    7 q+ P. E# Y3 \" y1 v0 C$ v
  44.                 context.AcceptWebSocketRequest(ProcessChat);8 t1 p1 v6 f  o: W5 a3 P4 ?
  45.             }   ?+ V5 L5 H# R2 k2 I$ k9 E; C
  46.         }& E9 ~  ^- H4 R$ ]& n9 u
  47. ; D  d% R; u4 B% r$ S, X
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    ! ^& y, R& d+ k9 W9 m9 x( v' g* T
  49.         {
    * [# a% d/ F$ l2 m0 D# R% m
  50.             WebSocket socket = context.WebSocket;
    ( H7 J8 D) I) `9 x. c
  51.             string user = context.QueryString["user"].ToString();: a% L( Z" F! e: O" U. X/ ?
  52. ' c3 `6 D% N$ F7 ^3 j
  53.             try5 j2 _+ W7 ^6 u8 P( X
  54.             {8 v) r" M% j- _$ |( M) ~+ r
  55.                 #region 用户添加连接池
    8 m& @9 G9 X! S! T
  56.                 //第一次open时,添加到连接池中; Y+ K: E% f8 S- _) s
  57.                 if (!CONNECT_POOL.ContainsKey(user))) C' L& G8 G* t
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    8 c2 ]* p0 v$ H7 d2 |, r+ D+ r
  59.                 else
    4 {2 [- I" e! H% ^. m& H
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    1 X2 @6 G5 _& F9 H2 r
  61.                         CONNECT_POOL[user] = socket;; @, M+ Z. z% A. q- e, Y( i' S( n
  62.                 #endregion, |, w: ?* D) i3 D/ s! l, G

  63. 4 s  [& g5 X0 {! F; s+ V  ?1 l' K) E6 t
  64.                 #region 离线消息处理+ z9 f, ^1 a; `9 Q
  65.                 if (MESSAGE_POOL.ContainsKey(user))7 j5 m! M3 Q$ m/ O! c( U. ~6 _
  66.                 {
    1 f. i4 E' u; p/ ~' B
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    / x  }2 F( V# ?
  68.                     foreach (MessageInfo item in msgs)) K% p- L  r" n, y
  69.                     {
    ' ^$ f/ H4 |( t8 @
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);' [: H+ o) w  B5 G
  71.                     }
    3 M3 N" l2 q" D+ A
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    7 m; q7 a4 Z9 D) X+ g' U
  73.                 }0 i7 K0 @% t! Q/ }2 C
  74.                 #endregion  ^/ r) G. y$ a1 u$ k
  75. / H( t9 @, ?6 E
  76.                 string descUser = string.Empty;//目的用户  [- E5 i; y3 a8 |' Y* v8 a1 c9 A
  77.                 while (true)
    6 F, n  r5 L4 t0 m. y0 x/ `) }
  78.                 {3 f( {3 L7 U4 R( N& D- u; Z
  79.                     if (socket.State == WebSocketState.Open)
    2 ~) U9 J1 m; j  S% F
  80.                     {
    7 j8 z+ T- H- ~1 |$ h
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    : `6 D/ Y9 }' }$ q4 j2 |
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    + h" ]/ |! |1 u  b( l
  83.   C. S( X6 l/ v0 x% M  U
  84.                         #region 消息处理(字符截取、消息转发)
    ) o1 y9 e* z' K# u
  85.                         try1 k/ \; D; X- [1 H0 ?' Z6 q
  86.                         {
    $ k/ j5 m3 T9 c$ E
  87.                             #region 关闭Socket处理,删除连接池
    $ y3 o" z# t" y3 ?3 s
  88.                             if (socket.State != WebSocketState.Open)//连接关闭4 t5 V  k& [* N( F* q) Z
  89.                             {
    * I; l7 a9 K' N1 e, L0 j) \6 c# c6 I
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池6 O. v2 `* D% X* g7 `' e
  91.                                 break;' y  J1 X( b0 B4 `
  92.                             }
    " s4 p; j9 k+ n% \" @8 a
  93.                             #endregion2 u- x( a# b# J$ L; j8 j3 c$ z

  94. , q% Q  @- V5 v6 j/ n
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    3 p5 j+ C6 X4 o& Z  `! U
  96.                             string[] msgList = userMsg.Split('|');
    6 W2 O+ ]+ Y1 z! u# e, c
  97.                             if (msgList.Length == 2)7 x5 m1 H! F( Z7 b* `3 O; n
  98.                             {) h' `/ n: Y; n, A; l
  99.                                 if (msgList[0].Trim().Length > 0); C) ~7 T$ {# c0 s
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    7 D/ X$ B3 M" t4 J) B
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));5 k2 U* k6 y( f8 |
  102.                             }
    9 Q* S5 K  N/ I" b3 V
  103.                             else5 g" k: h# q2 V8 O3 x" k, E
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));/ Q) w, S  r. d, Q% `7 _

  105. ) J$ h) C  o4 A( ?
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线! f" s* u$ G6 |5 z& }
  107.                             {
    0 z1 d6 j" t- l1 [9 R+ ]
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    1 G6 w* N5 B# m9 t2 o
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    5 b, Q/ b$ Z& ^8 Y; v
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    ! o, Q2 d) W) w7 O  T
  111.                             }8 j+ ?5 ]! _1 J
  112.                             else" i* C. D7 |/ ~9 C: c6 v% C* o4 \9 B$ v
  113.                             {
    6 k- J1 ]+ v6 k3 S
  114.                                 Task.Run(() =>
    6 e8 P- c9 h$ _; ^/ }
  115.                                 {
    % Z+ W1 y! ^+ B
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    . A* u$ h- z% w* A3 a7 _3 O
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());) v* D9 }% N+ ]
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息$ T$ r$ E( U" Y6 a( }
  119.                                 });" `7 A0 X( U! W6 p9 O5 \
  120.                             }% g) D9 Q) u3 G/ P8 \
  121.                         }4 [& ^7 m/ J6 s- |
  122.                         catch (Exception exs)
    $ d  t+ m6 Z9 L4 ^" p6 ^# [
  123.                         {
    1 N! m$ [: ]) _: o, l
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息# h* z- t0 {  c- j
  125.                         }
    " _# P- u0 p5 N$ y
  126.                         #endregion
    7 t# K# g) Z& \& I% `6 r
  127.                     }
    ( p9 V2 ^* Q2 D2 j/ ?" |
  128.                     else
    * h5 s7 Z4 `- }3 L
  129.                     {
      S7 ?8 \% @! g: _
  130.                         break;
    4 b0 ~5 a3 S$ W# K
  131.                     }) t9 p0 A" W2 S+ z
  132.                 }//while end
    2 a3 f- K) a3 \5 V
  133.             }
    ( b' x% z2 i5 H$ K
  134.             catch (Exception ex): D4 o; F7 f0 U3 l
  135.             {, ~# s3 F5 }7 g) N
  136.                 //整体异常处理
    + R* x1 Q7 R+ H- U  H" u
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);! o3 R1 y/ F  o5 w: u. W! C! C4 X
  138.             }
    & z! d4 O. t4 [' z
  139.         }
    4 B( d$ N! C; K& [/ K

  140. 7 u7 x6 I: j0 n7 a; ^) r9 o

  141. 0 ?0 A* O1 [9 q4 X/ a) C! d
  142.         public bool IsReusable, D! k; ~( d" h
  143.         {
    ! O+ y+ k& Y2 x% ?0 Z
  144.             get
    1 h2 R6 {1 ?0 O3 a6 ~
  145.             {
    # D' F  E. t. \7 p+ e
  146.                 return false;
    0 w3 p+ T) K: n9 Y& [: X. j3 M
  147.             }$ Q4 [& L2 n2 z1 X# V+ I$ z6 ?% s( \% k
  148.         }
    * R0 S& A& I5 r; x& Y
  149.     }3 f4 }6 i; n6 t. f6 L% a, R" r
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
- L+ x0 S7 Q+ _1 Z. \6 k9 W
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-20 11:22 , Processed in 0.135835 second(s), 25 queries .

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