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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

" V, }6 }1 f5 L% O2 z+ }
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    & F. J0 J1 n# f9 R0 Q
  2. using System.Collections.Generic;' s& `" G  ?/ g5 S: L2 [4 B
  3. using System.Linq;4 z8 f3 s3 {3 ]0 W( [
  4. using System.Net.WebSockets;" B! I) L# t* h! Q
  5. using System.Text;
    / M9 {; q1 X* r. p% H2 ]. |
  6. using System.Threading;5 ?8 r6 u8 V( L3 v. W
  7. using System.Threading.Tasks;
    9 p" x9 |1 P6 _; l7 D
  8. using System.Web;4 {1 h: q! K# v
  9. using System.Web.WebSockets;
    " b1 N: P# C7 J; Q
  10. ! |9 ^2 F, A; h5 A+ ^
  11. 9 F% n. d$ f, \4 ?
  12. namespace WebApplicationWebsocketHandler1 n! ~1 T3 `  j
  13. {8 w( \  E- P2 Y. ^8 O6 ?
  14.     /// <summary>/ r# F9 \, ?, Y# V9 I" M/ `
  15.     /// 离线消息/ H0 x! a' g9 S( w: F
  16.     /// </summary>
    ) R5 b& Q1 ~6 [) X, d' v
  17.     public class MessageInfo; ~: z' `* s9 i3 J" `
  18.     {+ O4 z2 [4 I' e  @0 O' Z- ^
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    + R' k/ N) n7 K+ j$ V& Q" x
  20.         {1 F. p5 z  @* W. o, J5 Z
  21.             MsgTime = _MsgTime;
    , {- _. U, }4 X0 K, F3 o
  22.             MsgContent = _MsgContent;
    , R+ b! N- b  G9 A0 N
  23.         }' e/ L( M5 f. a% A$ H' M( C
  24.         public DateTime MsgTime { get; set; }
    6 a. ?5 |" X/ X& P
  25.         public ArraySegment<byte> MsgContent { get; set; }. h; B) T2 z+ e( |
  26.     }
    8 _- M" M& r) j; @2 E" }
  27. 6 E" D# T0 M# s' J! `

  28. # ^$ x5 E! i! _, ]$ i
  29. ! t8 d7 n; f; j8 _1 z7 c6 y9 a
  30. 3 B. a& }5 Q3 J& Q, ~  p3 t# k
  31.     /// <summary>
    3 t/ O, P$ U( l8 j
  32.     /// Handler1 的摘要说明' W! F2 \/ ~3 |, r6 L/ M
  33.     /// </summary>* ?2 l( |; [. j$ M' ~: n% V2 x
  34.     public class Handler1 : IHttpHandler) k: v& m" b: F4 b& W3 ^  f
  35.     {
    " I" {) a8 O  s* a( v
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池8 U$ D/ e% Q. n5 i: u9 [
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池0 z( K# |7 O3 ?
  38.         public void ProcessRequest(HttpContext context)$ ~" a) N3 _  \5 q5 J# _
  39.         {8 A4 t1 ~8 s7 z6 ?6 M
  40.             //context.Response.ContentType = "text/plain";$ e) f- Y7 g  N& m4 m
  41.             //context.Response.Write("Hello World");' G4 ?6 p$ K- I
  42.             if (context.IsWebSocketRequest)) d. H- M% R6 a* L% {: A! p
  43.             {
    . Y. P: w& \5 R$ y9 f7 x% u2 `
  44.                 context.AcceptWebSocketRequest(ProcessChat);# q0 ]2 @2 D- H4 k* ^. h
  45.             } 5 b+ M0 p6 k+ ~  J% E) i! Y, }
  46.         }" ]9 _6 ?' n# q

  47. ! R7 Z4 K7 K) i* O+ T5 M' y! r2 u
  48.         private async Task ProcessChat(AspNetWebSocketContext context)$ w2 ?- ~6 \# u6 C
  49.         {
    0 v9 Y" {& v8 H& X" L- t
  50.             WebSocket socket = context.WebSocket;9 {* e# F) W( E( h& A4 \& a7 Z4 @9 Q
  51.             string user = context.QueryString["user"].ToString();0 X& a- }* [7 P) a0 Z3 K
  52. ) r* k+ Z0 V9 x( c
  53.             try; u9 Q& v9 G9 f4 M/ K
  54.             {
    9 b* U% N' O% b1 d
  55.                 #region 用户添加连接池
    " h& G2 k9 h; ^" _
  56.                 //第一次open时,添加到连接池中
    # }$ C( |! a1 m9 j+ Q4 o
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    4 G* W! A, I4 L+ C
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加2 D# G3 R8 B2 Q+ N9 l( L7 i
  59.                 else/ G* m  s7 c$ F
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新8 f8 k) c9 T, r, I" Q) N& F0 A
  61.                         CONNECT_POOL[user] = socket;
    0 D) [1 u1 @$ s/ b
  62.                 #endregion0 f+ H% l* g  H0 Z1 t) t  G

  63. 5 e: {- Z  p4 f0 I. z1 b6 l! ^4 X
  64.                 #region 离线消息处理  R% y8 e" u% t! H7 F" [- j2 k
  65.                 if (MESSAGE_POOL.ContainsKey(user))* d7 v* S/ o# F& v8 H- ^7 ~8 ?
  66.                 {
    + F# t/ X! N3 G$ f
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];3 v+ S- L" F5 @/ V
  68.                     foreach (MessageInfo item in msgs)
    # J4 o6 M2 c- P
  69.                     {
    % a7 l2 Z3 Q3 t2 ]# i" s# ~
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    8 Q* T/ x% F$ E* O! a
  71.                     }
    ' f/ \1 w* X$ n# Z9 B* Q
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息/ p: r: }3 s6 Q" `  t
  73.                 }  Y* i- @' _# n  w1 |
  74.                 #endregion9 H' s( o6 ?2 m; }% C

  75. $ R/ r$ {! N- [; `* B, _5 X
  76.                 string descUser = string.Empty;//目的用户7 n5 \9 U: Q4 S8 ?/ Z, R! x; f5 f
  77.                 while (true)! W* J$ f: X! d6 A/ A8 H
  78.                 {
    9 X3 q/ n& n7 }; ?' @6 x- T
  79.                     if (socket.State == WebSocketState.Open); |' \" o6 v6 A; u. U, a2 ?" F/ L
  80.                     {4 [: E) W* l/ [  ^
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    0 b# k% m7 }) Q2 f( l$ }9 x. }
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    / r  i+ c4 T2 D4 w( X, W

  83. 0 T+ r, |& r. J) k5 Y, E
  84.                         #region 消息处理(字符截取、消息转发)
    ) t2 p5 S* u  z% J0 O$ {) J8 M
  85.                         try
    " Y# L6 L3 \, p' Q0 w2 ]5 y
  86.                         {
    - \1 p. ~" K: c6 d) u! @2 S* o
  87.                             #region 关闭Socket处理,删除连接池; q+ s& {5 \7 z
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    : m, u: Q4 [+ @$ B6 `0 u
  89.                             {
    ; W) c3 g% k1 c5 m& F
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    ! r0 r3 X& x- C/ E1 z
  91.                                 break;3 C% N4 z( l4 @
  92.                             }
    % V  N( z3 o  V# b( ]
  93.                             #endregion% N4 u+ w+ Q  q

  94. % J4 a, n+ E+ V: A+ x
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息! t! W1 ]' O2 }, Q
  96.                             string[] msgList = userMsg.Split('|');
    : i7 a4 g6 m, d; E6 Q
  97.                             if (msgList.Length == 2)
    $ L2 P1 h! n( X( q
  98.                             {0 d, Z0 w1 _3 S2 L- S3 D2 T
  99.                                 if (msgList[0].Trim().Length > 0)4 q  k2 A( X' [% N1 x
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户0 O! c- w9 ^, d- Y# @8 O7 u! }
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    $ \$ o! f! G7 V+ `3 r
  102.                             }
    ' e+ d2 ~& q6 ?4 E
  103.                             else
    1 Z& Y4 r1 T( a( o
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));  G  p! @$ ]& H% b! y  A

  105. % x7 A4 E1 m; P7 B' d
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线7 K# K7 I' j2 H+ t. x+ i
  107.                             {
    6 R* x3 M; o4 f6 M- j
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    , e, m' _2 E+ R
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)" Z' _$ W' D+ ?! a# c
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);9 X% B& T6 L, [9 U5 F9 h
  111.                             }% J7 w5 T) ?8 q$ i
  112.                             else
    ' L- u$ j/ O9 m$ t" ]
  113.                             {/ r4 N( r3 x% U: O' o
  114.                                 Task.Run(() =>
    0 \  |8 b2 F4 o& [! S0 e( i
  115.                                 {  T( {9 L. k7 ~" h
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    ' I5 h$ _4 l  s; |& s
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());8 ~! C* H8 Q7 _6 t
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    ( u- s% n. H5 S" O/ @
  119.                                 });" w1 b- Q' N" _* p1 j. i
  120.                             }4 W+ @  G3 s4 i. p# M1 d; Z
  121.                         }
    . \/ c7 I! I9 H; I7 f# L+ d" e
  122.                         catch (Exception exs)
    ! D5 e& u, [( C; c: s  n# ]
  123.                         {6 y) J. B: Y$ b/ H: d
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    7 f- ]# @; u, d, i5 N! k
  125.                         }
    . c# M& S" ?" f4 L
  126.                         #endregion4 X" A$ W) W, t8 M/ N
  127.                     }
    ( V3 V/ F9 F- }
  128.                     else3 r  }9 @+ t* U6 I2 R
  129.                     {9 h" z4 O9 @, E% o! |
  130.                         break;
    # o( ]; O( t7 j0 _: T( a  y1 E. u
  131.                     }( n( D; p6 d( l" E* f! J
  132.                 }//while end
    ! |/ H5 E% Y0 @, T/ E
  133.             }
    & w* d3 c8 g  X: g# m- x# F6 Q* R/ h
  134.             catch (Exception ex)
    / R9 d" J- p1 t1 T/ d  a
  135.             {
    0 L2 I" M7 d, v
  136.                 //整体异常处理; a- R0 @6 X0 Y1 X# a; t
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    ) g& L* D& G3 Q' A
  138.             }: h+ ^7 R/ d9 w+ B& J: {+ L
  139.         }
    ) \( ~! E9 @5 d4 ^7 F( _$ c7 Q

  140. 4 g  g0 r4 ]# b
  141. 8 Z& u2 X7 T& Z# N' m$ C1 {3 C
  142.         public bool IsReusable
    6 z/ I: c3 F+ Y9 D
  143.         {2 d8 c' \% f. _  w" s: Q; ^  K- _
  144.             get; e) r2 R! P# w( e; O
  145.             {2 f5 d" u' d: K: y4 }( C
  146.                 return false;/ ~0 E6 Y# i1 Q' }
  147.             }0 r3 t/ Y* M3 N/ H0 i' E4 m$ f$ p
  148.         }
    8 d" k( r: _0 [+ N4 b
  149.     }
    ( ?/ z/ K5 w' m! |5 u) S$ V
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
7 W+ n+ M* ~+ @- Q
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-12-22 15:59 , Processed in 0.101382 second(s), 22 queries .

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