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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
: x% W0 F6 ~$ C
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
      N# I) V! N: V; D
  2. using System.Collections.Generic;2 b7 j& |6 P8 ]6 O' S4 D0 n& t
  3. using System.Linq;
    7 B* k5 W; X2 ~3 M2 h  [
  4. using System.Net.WebSockets;
    0 Y# J5 q" T4 h
  5. using System.Text;
    ! _. }5 ^. e: u
  6. using System.Threading;
    % |5 P3 Y* q! {1 g; e4 ?* z
  7. using System.Threading.Tasks;- q# C' N0 l3 R, M4 b
  8. using System.Web;
    - H2 y4 W- V4 ~" M( W& B3 P
  9. using System.Web.WebSockets;
    2 T' a' X6 v+ H" j: m
  10. 5 {5 P9 J: U3 n$ g$ m; ]

  11. & b0 z3 n5 W4 i8 d% _% J- e. c
  12. namespace WebApplicationWebsocketHandler
    $ J4 [3 [% u1 Y7 [
  13. {
    9 p! H, K6 ?3 F/ B$ A2 ]3 L
  14.     /// <summary>
      R9 |6 f+ D% W/ q' @* x
  15.     /// 离线消息: O7 b6 r2 U& w- k0 D$ p
  16.     /// </summary>
    8 z1 r4 k! B8 J) o; U: W# l9 a% q8 |  |  h
  17.     public class MessageInfo& ~0 f4 n1 i8 p5 \. o
  18.     {
    " N( O$ A- P7 b8 F2 W2 ^
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    ' r' z* o: G( z' {
  20.         {
    * I/ x! {# y( P
  21.             MsgTime = _MsgTime;9 n1 T3 H' D+ u  x4 ^# C
  22.             MsgContent = _MsgContent;( C+ K3 f, O/ c0 c0 D  }; k0 L. u
  23.         }* G' J: _& U$ h
  24.         public DateTime MsgTime { get; set; }
    # A, R( D( W; }) B4 f0 ~/ b" ]
  25.         public ArraySegment<byte> MsgContent { get; set; }/ C! o5 Z, I0 i* [3 s" j' E% z
  26.     }  B% [1 J! n& h7 S- }9 j) h( F

  27. # P% A) @  o* M2 H+ @

  28. ! t) m5 a% K" A, v! y/ t3 K

  29. , b- s% ?, ]' K3 v# H0 Q& X) k
  30. 1 S0 `( G" F. v5 R1 d" g- d0 @
  31.     /// <summary>1 ]. [6 n' T9 M1 Q9 f
  32.     /// Handler1 的摘要说明/ V2 Y- d9 V  B5 c7 L  G; `+ m
  33.     /// </summary>9 t5 B: i3 z* w, N- t4 ~6 b$ z
  34.     public class Handler1 : IHttpHandler& K. S! p7 [4 F5 s$ M% A) U, d
  35.     {
      Y/ c' A8 q* k1 F+ y4 L& ^
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    1 g6 f6 O- y9 O! B0 ?' Z0 s
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池8 i8 A2 S* H* U" e8 y. C2 t4 W5 o
  38.         public void ProcessRequest(HttpContext context)
    / G" p3 q& i: a5 L. B( c7 w
  39.         {% o& v% q& C8 \6 Z  Z1 v3 s
  40.             //context.Response.ContentType = "text/plain";
    ' y3 M% d/ r7 M6 q
  41.             //context.Response.Write("Hello World");! w5 ^9 ?# t& @5 y! I
  42.             if (context.IsWebSocketRequest)' _2 f( a# d  c" K
  43.             {( V2 e5 u3 |9 c0 J1 u! y# Y, j
  44.                 context.AcceptWebSocketRequest(ProcessChat);" H# e9 b: ^: D$ Y1 C1 }
  45.             } . B) z7 F  X" ^/ E
  46.         }
    & c! ~. L' L: f8 K6 \

  47. " a& g# X- e9 I2 C! S
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    7 h, C8 H* `# K- d9 _; M
  49.         {
    ! ~3 w) f8 K! _2 ]/ J/ I4 S$ e5 n9 I1 E
  50.             WebSocket socket = context.WebSocket;
    + k/ I3 S4 Y: \8 Q1 w! a$ X# V; y
  51.             string user = context.QueryString["user"].ToString();
    / I! S1 Z# w$ G# l! e6 Y$ ?

  52. : F1 H/ E# L5 s) ~7 Z- o+ U* O" n
  53.             try& l/ O& g/ W' F. C# B: U
  54.             {# ~! D1 i) |; W4 `
  55.                 #region 用户添加连接池8 z9 F# S. a. `2 ~: ~1 O4 k, G
  56.                 //第一次open时,添加到连接池中
      d& F& R" y- @. G9 f$ Y. \1 t4 q3 b
  57.                 if (!CONNECT_POOL.ContainsKey(user)), h' _& O/ V3 ?% _3 g! B
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    : w& @. U; t/ [# p% ~
  59.                 else! q" r1 P4 B% w! f/ p* J
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    7 X8 b0 u7 w: h, \' M5 m# {5 m
  61.                         CONNECT_POOL[user] = socket;0 v( G0 a' z& g1 S6 f) k
  62.                 #endregion
    3 v. w- l, c) B) d+ o! L3 h

  63. 6 m( z$ _3 E5 g2 h+ V
  64.                 #region 离线消息处理6 |& O. T" V8 q
  65.                 if (MESSAGE_POOL.ContainsKey(user))( n& E; }. `5 h* ~  \
  66.                 {9 F& |& S3 W$ R8 U) u* A) i
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];0 T3 l+ k7 f$ D  ~" L$ ~
  68.                     foreach (MessageInfo item in msgs)6 T; {" v0 i, m) X: I
  69.                     {
    1 I8 l% F+ Y% L6 @/ c1 [9 E
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    4 U  W" i0 y6 s. k" z
  71.                     }' D7 m( t& t% }
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息" ^( u: f. m5 Y7 p& }4 T
  73.                 }; ]8 G' s) l7 y! z
  74.                 #endregion9 Y4 ^" U% l( S4 h( U
  75. 9 c  S) ~$ i6 o& L6 B% W: H
  76.                 string descUser = string.Empty;//目的用户
    1 D; O# B( H& G
  77.                 while (true)) U3 Z: u" _+ q, x8 Y' o( O
  78.                 {* J0 i& Y/ Z6 `; `8 Q
  79.                     if (socket.State == WebSocketState.Open)
    " c: k2 P0 W- E
  80.                     {
    ' G& E+ s7 O& j! H4 W$ z! N
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);) ~3 d; N+ ?$ H" ~; \
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    " z/ ~% @) r) y$ a5 b1 W8 A) j
  83. ' X* f) M6 Z4 a9 M, }7 }7 z
  84.                         #region 消息处理(字符截取、消息转发)
    3 U& F8 {5 Y4 R" w* `4 _
  85.                         try
    8 N! a; }, _: N5 X* X4 U: s
  86.                         {
    . x; q9 U; [/ s( [
  87.                             #region 关闭Socket处理,删除连接池
    # F3 @' a; H  v) L* ^
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    / ]3 N) A# F2 R. q7 V# L% P
  89.                             {
    1 N9 X. o. b' b, `: J
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池! [! ?8 P4 T( v* J+ ]  A7 N
  91.                                 break;
    - h9 v+ ?+ X# X0 J1 l$ `
  92.                             }( A7 `5 }! g0 l7 f! _/ C
  93.                             #endregion
    1 t- b+ A& [" w2 C' J

  94. 5 ^! k. n7 m4 m- s8 t
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息/ O! E/ R! B. `! Z1 A. q
  96.                             string[] msgList = userMsg.Split('|');9 Q) Z& l  `1 p2 y/ I+ V: p- ^/ v& L/ a
  97.                             if (msgList.Length == 2)  j' Y% H  }4 z; w0 V+ b3 `
  98.                             {
    : x, ?& ^# W4 n+ N9 T; w
  99.                                 if (msgList[0].Trim().Length > 0)# t% J. N" ?8 Z, H' b
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户0 }4 ], m7 N% O" s/ l4 C
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));  W& Y' P+ `* L- E0 d
  102.                             }8 `5 U* g0 q6 z
  103.                             else9 _! H2 m1 Z9 `) H! @2 b7 t; p! P
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));3 m& u9 t5 I$ J( L! @

  105. # D( ?' O) o6 ]0 T  `
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线( B: P, S9 ^1 |6 V1 ~  p6 d
  107.                             {; R" i# C$ j) L7 C' t, G: }7 V
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    0 D% g. x/ a+ W* G( r: `
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)0 a$ P6 h4 A) @. [& w) M% s* k
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    % F5 ~( h2 I& T, P$ A. j
  111.                             }4 `, ~1 z( B/ v) f' [
  112.                             else
    5 y+ X  w& ?0 g6 U* r
  113.                             {
    5 _  I$ {- D  b% m! b
  114.                                 Task.Run(() =>- X/ G- f/ O, E# t  f  V1 _
  115.                                 {2 ^4 c1 F! x4 |8 [: Z
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中0 [, x  `3 H* T! R
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());: K9 n3 x' Z9 T/ ~: g. \3 ~2 W
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    * ?0 W: ?% c! V3 I4 q7 i
  119.                                 });# F6 R0 j4 A; I8 y5 V# x+ \7 v6 O
  120.                             }
    ) h5 t+ ]" O7 x/ U1 [& O- Y
  121.                         }- S% g7 ^. R& T5 L
  122.                         catch (Exception exs)
    2 m# K5 s* s0 i& I% Z4 V+ D
  123.                         {+ g# v0 J0 t/ T4 q
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    1 c& e" Z; Z* [, b0 y, p
  125.                         }) p% s* S7 Y# C1 e7 X
  126.                         #endregion
    ( {1 Z. g& q* A# Y: ?
  127.                     }; P1 M/ q- Y' z. ^7 L9 o
  128.                     else7 t# p5 g1 t! U6 q  _* n
  129.                     {7 l1 I+ o  f, K# K4 K0 Q+ R
  130.                         break;$ c3 e3 o2 C% @2 ]$ `5 ^
  131.                     }2 O/ b, Y, V7 E+ r
  132.                 }//while end
    5 L! @$ E: b  L/ w
  133.             }
    . j* ^6 A3 g! s# E
  134.             catch (Exception ex)0 K1 k, \7 _' o: Q) e& W) P
  135.             {
    / W! h. c1 t  F) ^* {4 j
  136.                 //整体异常处理
      ~& q  g8 K; C  v9 v6 H+ K" h1 U! e
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    ' ]- O: E# |4 u, a0 R
  138.             }' S1 c1 A  R. N- V
  139.         }+ r; r6 t# M4 w/ G" a

  140. 8 \; I6 t  H7 |9 ?2 Q% D

  141. 0 z" ?, ^, |) I1 Y6 }+ V/ x
  142.         public bool IsReusable
    $ `" \+ m: _4 H3 I$ T- P
  143.         {
    3 _; J7 f) i9 \$ _+ e0 ]3 g
  144.             get# f6 M1 L1 _9 R) Y: J  N) e
  145.             {
    9 a5 q7 L% f! Y- c
  146.                 return false;
    4 f( e5 A# Z# `! C1 }5 K
  147.             }) J! K' ~" V! Z7 m& A& x+ w5 Q
  148.         }
    ; T  T' Q3 G/ |9 G! j- z( }
  149.     }
    ! \: t- ?3 E3 O. T% E! U4 t9 g
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
; j; G8 e1 [" r. f+ H" c
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-3-16 17:25 , Processed in 0.060158 second(s), 23 queries .

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