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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

; o" S0 L" R" V- F* Y: y; d
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    ( q  ~- C8 J- ?
  2. using System.Collections.Generic;$ v6 B; ], T* `- q
  3. using System.Linq;
    , m7 t5 R4 J* d
  4. using System.Net.WebSockets;) @/ K+ E. B" n; v& O5 x9 f
  5. using System.Text;
    ' m6 d2 U+ G6 g; ~7 v, t
  6. using System.Threading;- X, Z7 v7 [$ g* }1 L* x0 a
  7. using System.Threading.Tasks;
    ) b0 Q$ H2 v/ x' b' [7 R* p
  8. using System.Web;
    % k! A( g( ?( o: x
  9. using System.Web.WebSockets;4 f- @" x% g/ ^3 `
  10. - l8 W/ d# y; V% `  p2 W7 e& @! ~

  11. 8 \0 X6 p1 X, {+ M+ k
  12. namespace WebApplicationWebsocketHandler, P# w& W% Y$ J- x& P5 F( R+ e# _
  13. {
    2 T2 r* f- u" C; x
  14.     /// <summary>: U/ d4 o4 s: [  r& G
  15.     /// 离线消息
    ! Q1 t, W  ?) R+ G$ n
  16.     /// </summary>
    8 P- D+ q) z; w2 a1 j2 c1 g7 c( \% z
  17.     public class MessageInfo
    & Q3 V( D* f/ q" @$ k4 @* I7 Q
  18.     {
    ) Y) Q3 W( h; s
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    3 P( p4 V: [% G3 f& U
  20.         {
    9 P9 G) T* p6 Q2 C2 X
  21.             MsgTime = _MsgTime;( F5 u: }* t0 T. ?; s. S5 P  W2 Z$ b
  22.             MsgContent = _MsgContent;+ l+ S) ^' K  a7 J8 `
  23.         }/ Y+ w5 ]; H, D2 W' i
  24.         public DateTime MsgTime { get; set; }
    ' |) [/ Q5 o% I+ J
  25.         public ArraySegment<byte> MsgContent { get; set; }- v8 a& J+ d7 q% t1 D
  26.     }
    : \: _2 t/ g2 k* n( T7 c

  27. : V9 a  j5 k* }5 R' g" O6 N: b

  28. * K( `1 U) }) B" O% O; v

  29. & R) I& V% f. K; ]6 _! N' ^

  30. " x, ~& L+ }# R  f! p* T! Z( I
  31.     /// <summary>" s  g; s$ R/ X8 r  ?3 a7 ~
  32.     /// Handler1 的摘要说明3 j% s* A' Y5 w1 n4 L/ J( D0 n+ h: o7 f
  33.     /// </summary>
    * N) L" b7 l1 v) ^8 ]. }) N
  34.     public class Handler1 : IHttpHandler
    7 f. z; Q, k7 ?! [$ G# J" Q' g
  35.     {
    ' h) O1 a, \- A& ~, l& G! M
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池# O; v. Q0 p1 ~. O
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池8 m  t3 Q  P5 a- P+ t& t$ Q
  38.         public void ProcessRequest(HttpContext context)- {: n# p" e1 o) n
  39.         {
    / ?% k1 A8 A: i# H2 D4 V! P& s9 K
  40.             //context.Response.ContentType = "text/plain";
    9 H, w" `1 O4 m! ?0 v) n7 U
  41.             //context.Response.Write("Hello World");! T4 a. L: {$ h9 o! j
  42.             if (context.IsWebSocketRequest)0 B# @( |" k9 ]* D+ t" ]
  43.             {) d4 M% {+ A3 w3 }
  44.                 context.AcceptWebSocketRequest(ProcessChat);: x& V. N- w8 C1 D8 b
  45.             } / o$ Z7 s6 h/ t/ U
  46.         }# f' O! D& x! B; d! m0 h, b

  47. / Q1 L( J$ b9 l9 W9 F) V4 e
  48.         private async Task ProcessChat(AspNetWebSocketContext context)" e5 g; E( P+ U! ~# [3 c# n
  49.         {: q  m7 c$ O; @5 u+ q) @/ k$ P' m
  50.             WebSocket socket = context.WebSocket;
    5 H/ X$ U, f; G: a: J/ b; p
  51.             string user = context.QueryString["user"].ToString();8 j+ T+ W2 G3 U

  52. 5 E) f, K0 X7 P- Q8 {6 m3 G
  53.             try
    ) Y$ C4 a1 W6 R
  54.             {
      P1 p) ]- K- a2 ?, w& m: u+ t! D  ~
  55.                 #region 用户添加连接池
    ) i$ k; M$ x( _8 i, G3 B, E
  56.                 //第一次open时,添加到连接池中
    5 o' X' R0 \6 Q: G7 a- ?
  57.                 if (!CONNECT_POOL.ContainsKey(user))1 L9 j2 a) L- N, m# t
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加  d8 f( W; X$ L% R! z& D4 V
  59.                 else
    $ ^: ]' @- p7 ^+ Z/ ]- e
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    7 }! w. i, g7 A
  61.                         CONNECT_POOL[user] = socket;3 V% \/ i$ ^+ B
  62.                 #endregion) e+ q! D, x# [0 e

  63. . x/ q9 Z: F+ J+ ]; M' ^0 w! q
  64.                 #region 离线消息处理
      l/ D' j7 c: N- B3 \  I- c
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    ; R9 l* C! S% y4 w
  66.                 {1 k1 s; d# q$ P' A1 q7 F
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];0 s7 V3 k2 [. W, e, i; u
  68.                     foreach (MessageInfo item in msgs)
    ! i$ o* p5 _3 l. w8 }+ I
  69.                     {
    + ?6 A- |$ ?& h* H
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    * D* _7 A& M6 N- {
  71.                     }5 O" ]# s. ^+ D* I, E! H' d
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息9 h) w5 Y* M4 d! _, W$ |
  73.                 }( y5 Y2 o. n+ x) d0 H
  74.                 #endregion7 F$ t& g0 s' W9 [. ?
  75. 4 e' x' _! a# Y% v; t
  76.                 string descUser = string.Empty;//目的用户
    ) u; N# W: |( U& B8 A$ k$ z9 R8 A. @
  77.                 while (true)* T" y$ Y$ A) G! z( o( o3 S9 [6 {. q
  78.                 {* }9 @9 Y8 q4 O5 b: C) B4 _
  79.                     if (socket.State == WebSocketState.Open)
    2 Y" c% a6 h! z3 B" v
  80.                     {
    5 s0 |% ~7 P$ L
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);/ m: V3 R4 B& h5 P+ h1 s
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);2 R* ^5 N) y* A# i2 I( B9 G' H

  83. 8 v# X4 H: f6 H( Q0 `; c+ y
  84.                         #region 消息处理(字符截取、消息转发)+ R+ i+ Z  z" E' ^+ L' Y
  85.                         try
    / Y! i* `  t6 B* a3 m* m
  86.                         {
      p( b5 T- x* C, A" p! J; S8 E
  87.                             #region 关闭Socket处理,删除连接池
    4 r6 J& M+ a1 V6 ]$ _7 S  Y
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    ) ~  [% L( E/ Y$ V
  89.                             {
    % R, }' [' _. M/ E1 m( r
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    ' W% b# U! v7 ?$ X( k7 N0 H! U  x
  91.                                 break;
    4 J; w: H8 v4 B( l8 }
  92.                             }
    1 g1 b4 c9 n# [! p
  93.                             #endregion
    ( R- i  `/ f- r

  94. 8 j" I8 k9 v3 p0 \+ W
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    & r' P# C* e- m+ r. ?' G: c( O- D
  96.                             string[] msgList = userMsg.Split('|');+ }* y" K6 J# R. u) R1 o4 W
  97.                             if (msgList.Length == 2)
    2 w- }4 E/ e' t5 V- ~
  98.                             {
    7 u+ j: @( Q, ^
  99.                                 if (msgList[0].Trim().Length > 0)
    9 s4 I& r/ x* r8 _; a6 ]+ H
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    ! x' y0 v* f4 s, q8 L7 a
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    ( Z1 m0 r. N( x$ h) e
  102.                             }
    - B& e/ {! O; t
  103.                             else' M+ @! W4 M9 U  x
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    ' [( Z' o( p. m% m

  105. $ G6 s/ Q* ?3 i5 a* C4 s
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    " ?7 C6 w/ r! [- f
  107.                             {
    : n7 q  L/ P; B, p# D
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    ; C; R, J9 Z4 w
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)' `* `% l' Y3 j' f& T6 p8 K- a1 b
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    + G$ K  x% v' e# }+ ^  @
  111.                             }
    1 w' d' y9 w# W. R/ |" p& G0 @- O
  112.                             else3 {# x0 u4 h: ~: C& i8 t
  113.                             {9 u% J% H+ ]' y- ]1 O
  114.                                 Task.Run(() =>
    5 [" b' q* c& `% N( ~/ b
  115.                                 {: m: P: _' o5 H, [' ^: y% ?7 A2 w
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    8 u, ?! l( n1 y' {8 U; Q
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());$ N- i* k! u4 Z/ ]5 h# Z
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    $ J; K- ?- `7 q5 @/ a: {
  119.                                 });
    , Y1 m! S2 {! S* a
  120.                             }
    % Y) d, S4 y& \% y: C' f
  121.                         }
    5 j8 s, ?7 \' j, J# _' e0 a# H
  122.                         catch (Exception exs)
    7 I! i. a, }. V$ n: c
  123.                         {, B2 t, v0 n  x7 A
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    # |; F% s$ x- N
  125.                         }
    , ^' C! u8 m( d& g; K& T+ u
  126.                         #endregion
    7 \/ ^, ], w) G$ D/ C# z* s  d
  127.                     }. k8 G6 G: @, T
  128.                     else' x$ f2 h9 Z- T! x
  129.                     {! H' W0 V& h, }. F3 g" _/ u
  130.                         break;2 F# t2 ?4 S- b
  131.                     }1 d; J+ C( `7 u2 p: l, ^6 q8 P
  132.                 }//while end
    & q( _4 `  s4 J6 g/ k  _7 K' J: A
  133.             }
    2 r  U! R  g" S. M* p2 z* F
  134.             catch (Exception ex)
    ( Z, V3 Y& Q4 b/ ]6 q2 T
  135.             {
    % k) z* W4 `3 R5 ]5 s- p, u
  136.                 //整体异常处理
    % e$ Z9 r( k# L5 _
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);  I2 q4 N& ]- n& Q
  138.             }
    4 P( N" M. Q& s+ J& |9 Y0 h' s' e
  139.         }  v% J# @* c7 h* [. I2 W

  140. 9 `* P2 ?- G2 p  E5 H

  141. ( i2 I. _0 g: L1 t4 x* h
  142.         public bool IsReusable) k* Z  E/ M3 o: Z: g! m; q  u
  143.         {2 m. o/ y1 ^: r7 L+ w; Z
  144.             get7 |* V7 h6 H+ O. r9 c9 s1 _. o
  145.             {
    * H8 _" T& o/ [. d' K* l
  146.                 return false;, Y! R8 b- X' g
  147.             }
    / n7 ~8 R  L6 K% t6 s
  148.         }" p, o( {' v% I- C- k# G1 K2 y) r9 r  Y- |- ]
  149.     }% B" \- \1 Q- F2 N
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
7 H) e: L0 w$ W- {. J; B- u7 E
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-3-16 18:46 , Processed in 0.054003 second(s), 23 queries .

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