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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |正序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
$ O8 F: n! N- s
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;" F( K0 ^# ]( n+ e2 N. D0 ~% |2 R# J
  2. using System.Collections.Generic;
    - M  j- c3 w/ P5 {
  3. using System.Linq;
    " B" q+ D7 A/ A1 S+ Y- E
  4. using System.Net.WebSockets;
    % w4 I& S% r- A4 B( b: Y: w
  5. using System.Text;) K, D: o0 [' |+ P' P3 N( v
  6. using System.Threading;' }: K# \5 k+ B
  7. using System.Threading.Tasks;
    ( u1 z' n* M. _
  8. using System.Web;  G# q( k. N! P" Z8 |
  9. using System.Web.WebSockets;9 z5 b: g5 S2 O* G' a
  10.   G6 d8 z: U  T/ ~  M

  11. * r, O: [6 N% a3 [& e) P
  12. namespace WebApplicationWebsocketHandler1 c& O4 p: U' H# y2 Z
  13. {2 ~+ t- |2 s) g- t8 f
  14.     /// <summary>
    : @$ t% W9 J' _8 ~- H+ w
  15.     /// 离线消息8 S/ L- i9 Q4 q2 w: z$ o
  16.     /// </summary>
    8 H2 y/ ]! A; d( B
  17.     public class MessageInfo
    + Q4 o0 p; u$ p
  18.     {
    " @/ I. j0 p6 j" T6 B: u
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)8 ]/ M+ L1 K, L
  20.         {
    2 F" f7 I9 W- F8 L7 _
  21.             MsgTime = _MsgTime;+ T2 e- c' V3 A1 n; q! Q1 S  w' g
  22.             MsgContent = _MsgContent;
      }+ `! z1 v3 I! d7 q* O, g
  23.         }2 r6 y& q) N1 M4 b7 Y0 Y( j6 f
  24.         public DateTime MsgTime { get; set; }3 ]  b2 y7 b. G% {& ^) d5 A
  25.         public ArraySegment<byte> MsgContent { get; set; }( P0 d! i: J2 l$ C# d8 ~
  26.     }
    . _  B( }9 Q2 x1 O) r& p

  27. " Y; e+ a4 v  F4 C  _

  28. 4 b# O7 [9 q/ X. D
  29. , u) N+ q% j0 d! K
  30. 9 l- A, m7 \1 e6 I" l: L
  31.     /// <summary>$ j1 C7 i+ u8 ?' P8 |
  32.     /// Handler1 的摘要说明
    1 ^& M* e2 D8 P9 }
  33.     /// </summary>
    + D& `9 {* S; v
  34.     public class Handler1 : IHttpHandler
      [* X. ]8 e( q+ p2 i& ]# c2 {
  35.     {
    9 \- z' {5 U; K% A( c! x
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    . m4 J. m0 a7 n% {, S- ^& ~( Q, J( m  X' v
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    + ?! h8 m! O  W- r2 J% f1 Z
  38.         public void ProcessRequest(HttpContext context)
    + H: J" a2 r* i/ M/ E. L
  39.         {$ ?! z/ Y" P7 W, r5 b' y
  40.             //context.Response.ContentType = "text/plain";; }: J( n& w# r4 h5 j- F
  41.             //context.Response.Write("Hello World");' \9 v3 c% g0 |! ^: u
  42.             if (context.IsWebSocketRequest)6 U) ]; ]7 [3 C# }, u
  43.             {
    2 p. `8 K# P0 u$ l+ L0 A4 c  J2 R
  44.                 context.AcceptWebSocketRequest(ProcessChat);' O! Y5 d; X: ^' o; u
  45.             } " c* Y4 L% a7 A( _
  46.         }5 J: _& f+ u6 }0 ~4 o
  47. : r8 D% n" D( T, b% X
  48.         private async Task ProcessChat(AspNetWebSocketContext context)6 T+ y3 t$ U; ~: E3 i% j* ~
  49.         {8 W! b2 e& \4 ?( r7 _
  50.             WebSocket socket = context.WebSocket;
    4 N) l! X7 o7 R: m
  51.             string user = context.QueryString["user"].ToString();% ]0 l# J" N/ r% _

  52. % r4 k5 b0 H* i2 k
  53.             try
    3 f% c3 X8 t8 B
  54.             {# S7 R; n9 T! X
  55.                 #region 用户添加连接池! f9 W- i' B! i
  56.                 //第一次open时,添加到连接池中
    , k  x; v) w( t! N. r; I' T
  57.                 if (!CONNECT_POOL.ContainsKey(user))2 h6 R; e/ n0 s8 j
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    # b+ @( P" J! F4 }8 ]; J4 g3 `5 t
  59.                 else
    ) t2 {" h; |5 p1 v5 D
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    % ^5 c/ d$ Z3 L9 n& K! ?( I
  61.                         CONNECT_POOL[user] = socket;
    7 t# `5 J# Q  @9 i/ D" f
  62.                 #endregion
    + N  m) P1 }/ k  Z7 P; l

  63. 9 N3 }5 p1 |" o) z! K6 t+ o) C" w6 S% V2 c
  64.                 #region 离线消息处理
    3 K/ g/ K3 h3 e* r  G5 R) V7 x
  65.                 if (MESSAGE_POOL.ContainsKey(user))+ p1 O: D# t# G% O( G
  66.                 {
    6 T2 @# e% @0 t! m; J% F! M
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];9 E, O$ p- u9 x- v
  68.                     foreach (MessageInfo item in msgs)
    ' V) q5 s6 u* O7 F% |
  69.                     {
    * ?; o, m! E5 ^1 B2 N
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);4 D4 q. a& j4 U% y' y
  71.                     }; B3 N/ p% Q% A9 z. h
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息0 N& t( S3 M3 f
  73.                 }+ x4 t' L* ?* T6 Z2 z1 ^
  74.                 #endregion
    # z! I) C, t6 e$ d" |  h/ l. `# x! ^; k
  75.   M0 r4 c% A3 T2 Y1 [
  76.                 string descUser = string.Empty;//目的用户4 O% T& |6 H5 z9 {: O
  77.                 while (true)6 _4 A' N; v: ^6 e
  78.                 {+ `4 b4 I0 _; W+ Y3 Y; F8 ^! J
  79.                     if (socket.State == WebSocketState.Open)% r5 V/ U6 g) h6 K2 d
  80.                     {- z+ @/ U& c" j7 t
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    2 A3 B" N; k- c- S0 V
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);: ]9 F# e8 H$ C6 S! Q/ `8 v1 P
  83. & @( I  ?" D. T
  84.                         #region 消息处理(字符截取、消息转发)7 W: _7 f: Z! ]1 _% a
  85.                         try# {8 P- c: J- Y- u: g. e% U  p5 \. Y
  86.                         {2 s, p" @; o) k; O
  87.                             #region 关闭Socket处理,删除连接池6 ?  ?# \( P& k+ h1 {
  88.                             if (socket.State != WebSocketState.Open)//连接关闭. }" E$ `' n# [  S6 s
  89.                             {
    " R, J2 I7 S6 z% T. e
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池6 b6 _( H9 o9 X
  91.                                 break;, h& S; c, ^3 X1 |" `
  92.                             }
    # B; M2 T0 s1 I, q* u! t; ~0 Z
  93.                             #endregion  k9 H4 _1 N4 S1 e; b
  94. 7 B$ S; H: ~+ F" J
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息% }  z$ h( v- h5 P$ H" ?
  96.                             string[] msgList = userMsg.Split('|');& I: ?0 q' A+ ~% v
  97.                             if (msgList.Length == 2)
    # I# g+ n1 K5 j9 E
  98.                             {
    ) K6 s1 c0 @! {1 y4 A2 k7 T8 S
  99.                                 if (msgList[0].Trim().Length > 0)
    + \1 s+ Z5 n$ g2 X" s$ S0 Q3 y. ]
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    " o+ R! n. y: O
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    7 {. p0 z  C5 V# M! q
  102.                             }7 W5 J1 e- `9 X& w8 [* b
  103.                             else! O8 B0 m4 J1 p9 _! W9 X9 C
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    ; m  F* o4 J$ R9 M# |

  105. 9 m/ j' w. @8 f8 {) t
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    9 ^6 j) A4 R+ g
  107.                             {
    " ~1 o3 R0 _4 t+ D/ Y; x" G
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端* }- S% h! Y3 H$ G# L
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)% g& K3 v- Q' [1 p. U3 @
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);& A2 m* f/ X  r& o7 A; G$ y+ S
  111.                             }
    . X" R% X. A# u, i3 U& E
  112.                             else
    1 }+ S' j2 o" y" s: j
  113.                             {
    8 j# Q  u2 h( s/ o, A0 l
  114.                                 Task.Run(() =>( c8 b! F+ N/ l* n
  115.                                 {; T" a' v. j4 {4 k
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中, d8 M7 F! C9 ~# ^
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());  H  A2 h# Q! f5 i) ^8 m4 k  @
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息% j  e7 w4 D( s& ~( \
  119.                                 });# a/ ^3 I3 V: M6 ~2 N. n
  120.                             }9 j$ b' P# |* U0 w
  121.                         }7 h6 y/ J+ @5 p: i8 r/ y4 @
  122.                         catch (Exception exs)
    ( |1 p8 d: `' b% ?$ T+ h# W
  123.                         {
    2 s; j- ~; [$ q
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    4 J) S0 Q& L- @/ h3 U3 n- a8 D
  125.                         }: m) T, |: W% S( q1 J9 c/ v9 u4 \
  126.                         #endregion6 H/ J% w  D. ]0 x6 H
  127.                     }
    / i5 p/ i8 f8 x" p
  128.                     else% ~0 y$ V5 ?+ ]8 z9 d
  129.                     {
    : [' P1 B, U% c$ k4 O5 N! @
  130.                         break;
    0 [0 v* g$ _$ S3 y4 c
  131.                     }4 d! n. S2 [! c
  132.                 }//while end
    4 j; h5 h3 L2 ]% u3 a8 \
  133.             }
    ) C) Y; f+ b* A$ D9 Q
  134.             catch (Exception ex)! L; U0 ]7 }$ B4 s
  135.             {' Y- c5 n* k' }* ?7 ]& x
  136.                 //整体异常处理
    6 s( d9 n$ `) x# r
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    1 r2 V/ _! J% P; q6 L: e3 j( `4 e0 d* E
  138.             }
    ; H! J+ r; s: U& e. k# N3 v% @9 G1 q
  139.         }8 g6 B0 R' E1 I( q- m: I8 h+ o3 H/ ?
  140. ) `! K4 p) q- {

  141. # P% d; K8 S+ ^; |  D* }
  142.         public bool IsReusable
    $ u, ?* r9 ^, K% w
  143.         {1 P: c; i1 K6 }$ H) N8 T( h
  144.             get' |' m# `2 _( K3 p1 R/ C
  145.             {: ?3 n2 C9 Y3 j0 H) y
  146.                 return false;0 [  W* X# M5 q
  147.             }
    6 k( e) a+ ~7 T/ c9 f, z! }
  148.         }
    7 Q+ z8 y  U2 p: [. H3 D# F4 b# s7 o
  149.     }
    6 ?- X4 ]9 T, e* A
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

7 j6 S+ Q* a7 I8 L1 B' m4 g
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-5-4 16:05 , Processed in 0.069973 second(s), 25 queries .

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