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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

; N. o3 q! x1 B/ `, g
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;6 Q5 Q) }- i5 C3 A1 x, q' [' ?
  2. using System.Collections.Generic;4 u4 D$ x9 T  t* l
  3. using System.Linq;
    7 v. z! y- T+ {9 @- {2 u
  4. using System.Net.WebSockets;
    # v% j; I: Q5 e! E' L2 C
  5. using System.Text;
    * ?9 B& G5 I+ j3 I6 a" E4 s
  6. using System.Threading;
    ' W( H/ N# z# s. M7 V- @# Z
  7. using System.Threading.Tasks;" G+ f; Z9 a" N% H: Z
  8. using System.Web;3 M. |% \0 k4 |9 s  w$ a
  9. using System.Web.WebSockets;# o7 Q! l- ~+ n

  10. 5 |6 s/ X  }4 f- y  U
  11. , `' w: v) I' H7 H! T
  12. namespace WebApplicationWebsocketHandler$ I8 A1 Z) S* e! p
  13. {
    & G+ s- K: H7 m+ m3 v) m
  14.     /// <summary>
    ; x8 x8 F: x' l) Y* N
  15.     /// 离线消息
    1 t5 ]) w3 L( H8 Z2 |9 E
  16.     /// </summary>
    ) x# `; t- X# Q
  17.     public class MessageInfo; E% E4 ]. x1 v
  18.     {. n2 ^1 E& \, N
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)6 I% z6 x" D% B# |- N/ R
  20.         {7 E/ _( k5 |0 ]- f. [" k
  21.             MsgTime = _MsgTime;
    * g% X0 F1 C+ o4 v1 w. I" w
  22.             MsgContent = _MsgContent;7 S6 g8 y- P- \) y
  23.         }
    6 Z) x$ d4 I! e, {
  24.         public DateTime MsgTime { get; set; }
    / D2 m" O& v' @* D
  25.         public ArraySegment<byte> MsgContent { get; set; }
    0 h$ b0 C- A! m4 `2 C
  26.     }9 Z; k( c# y  Z  f
  27. 4 c0 g: N; L" |3 I9 u% z
  28. . h( ?: }% I8 Q6 q5 U- B! \

  29. 4 X6 q4 n+ f) a6 N7 d4 Q1 V

  30. 7 H% H$ o5 b. E! }
  31.     /// <summary>7 g" t- s$ v9 Y6 T, F" N
  32.     /// Handler1 的摘要说明$ w5 C2 L' T9 z
  33.     /// </summary>
    3 \; g- P8 X, Q. x6 ]
  34.     public class Handler1 : IHttpHandler7 G9 u: y/ K& }0 P
  35.     {
    ' q7 F* Y5 }2 F- a+ l  d9 ~* t7 G
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    4 F# }! a0 a4 I. b/ ^3 B5 N+ E1 v
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池/ F) \5 l7 s- v/ M! J
  38.         public void ProcessRequest(HttpContext context), a, y  T: r4 a: ^* k
  39.         {' |5 M& m+ _, k+ c3 e. O8 [
  40.             //context.Response.ContentType = "text/plain";. U4 _: D: @' `0 v
  41.             //context.Response.Write("Hello World");- {. s9 \- ~* Z9 b3 d7 t) @
  42.             if (context.IsWebSocketRequest)
    6 L8 J) ]1 O- i5 ?- u7 Y& I+ Z
  43.             {
    0 B9 x2 C# A8 V7 I# K" J
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    * `$ v; A% F3 i8 E* l
  45.             }
    ! Q$ |' {$ p1 ^
  46.         }! m1 A& S' W  j0 L  P! Y9 G

  47. + t; D, k% I1 Z- x' k* @
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    3 A1 p. }7 }5 d' ?
  49.         {
    8 t2 |$ a# ^/ Z0 v* f3 `
  50.             WebSocket socket = context.WebSocket;5 |8 a! D" _! }1 b
  51.             string user = context.QueryString["user"].ToString();
    ; n6 F" F! b) ~2 S& M
  52. # v, \+ d3 x, S6 b7 }& T' u4 J$ ?* }
  53.             try
    / A' S! X; J/ P7 W# |
  54.             {6 s7 Z( t) e$ \% ]! j: f* h
  55.                 #region 用户添加连接池
    1 W0 p; ], N% M  N0 d$ y
  56.                 //第一次open时,添加到连接池中
      W* ?: q- Z$ N% H/ D7 r% v
  57.                 if (!CONNECT_POOL.ContainsKey(user))" ]+ D* W: ?: R, k5 c0 ]
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加, J: ^3 T; P- K3 r$ c' I
  59.                 else
    ; }5 b5 `- o# z! _% p7 {1 i: j
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新; u4 Y; `# u0 R1 L+ f
  61.                         CONNECT_POOL[user] = socket;3 W  W8 l- p. T4 w
  62.                 #endregion- n- \/ I( w9 M3 t: z8 D2 ?

  63. 6 r% `8 p! v( [% ]6 m- [  r
  64.                 #region 离线消息处理: T# G# [* c* y2 y# I7 A, R# O- q. D7 j
  65.                 if (MESSAGE_POOL.ContainsKey(user))' m2 S+ r+ e3 |" _
  66.                 {
    9 a2 w8 O2 J& u
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];& p' a+ m9 J& K3 r
  68.                     foreach (MessageInfo item in msgs)
    1 ]$ x' n& k# L9 C4 H& ]6 [
  69.                     {
    ; m) _! o/ Y( h5 q8 ]7 M" Y/ u
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    $ m0 U, Y! z& J4 z% u4 D+ R
  71.                     }
    ; M) ?, o' v# {5 c" k0 b# }, Q( B
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息  W% z, V2 h+ N. R* C- |/ D. Q
  73.                 }3 y6 e$ H( i/ c$ `
  74.                 #endregion4 `; o) l3 @- f' b8 g0 g3 X

  75. ; J- v6 @6 \) L7 {
  76.                 string descUser = string.Empty;//目的用户
    " x; s* G, ^: e( @) J
  77.                 while (true)
    8 k- E; p, E+ M9 K
  78.                 {
    # h- a) O# u: ?, _4 ^
  79.                     if (socket.State == WebSocketState.Open): X" D. z  }6 A$ ?0 p
  80.                     {
      i+ |4 W$ O( L" _
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    0 N" L4 D5 L: f2 P. \0 }1 _
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    $ U/ x( c+ w( R- @
  83. ( f# K8 b4 O6 A
  84.                         #region 消息处理(字符截取、消息转发)! w; Z6 @5 b! q9 f$ J# x
  85.                         try
    * k! h& Y; p/ b' ]. T$ C
  86.                         {/ d4 \5 }* @$ d0 @% y
  87.                             #region 关闭Socket处理,删除连接池* l0 V& V3 Y( s! I- Z0 W( p
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
      U+ L! _" L& F/ a+ b
  89.                             {
    ) c1 {" ^3 c3 u) u3 I4 Q
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池' R5 J9 p" _. p4 g$ Y! D1 O: v7 U
  91.                                 break;
    ( C( m+ |+ r. i% M+ ^
  92.                             }
    " `* y: K+ w4 J3 V* m) e" D
  93.                             #endregion5 q' |# H3 e4 r: j8 Q7 P+ _

  94. ( v+ F1 T) n/ Q  O* t7 H
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息; p0 `8 i& p& u
  96.                             string[] msgList = userMsg.Split('|');
    + G  v* z9 M4 R, @0 o9 g' o$ L! |. p
  97.                             if (msgList.Length == 2): P9 S8 r* f% x9 K* P
  98.                             {, M) {2 f" A6 e$ q
  99.                                 if (msgList[0].Trim().Length > 0)
    ) k; p* k; w. w6 M6 M0 a" w
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户% N3 t1 m8 E6 [
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));1 Z% z' A  d8 L8 R
  102.                             }
    1 x. E1 [2 R5 l! Q
  103.                             else' {' a* f0 R- l1 o. }. c6 x
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    1 `1 U2 L( V' u( m/ U( }  \
  105. , X# T! Z  a$ ?
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    5 }/ B0 W$ _, E1 m! h* Z
  107.                             {
    & L% K! C0 N+ P0 v3 d5 p% O
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    ' b0 x* Q  M: T# }3 S
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    $ i( d( @: D/ `2 g* Q
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    9 ?3 Q" J- q" O  |% V
  111.                             }
    $ }+ ]8 {5 F+ J! B: M
  112.                             else
    / _; `2 e1 }% ?. n4 e# }4 m" Z
  113.                             {
      j/ `" n& m& [+ Y# k
  114.                                 Task.Run(() =>
    ! m8 K( y& e4 f, M( s' F, q5 k
  115.                                 {, }* v4 P) z. a
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中, B; l7 `0 ^; _# `
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
      J1 v% G2 x0 W/ x3 h! o0 V
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    ) U, T: v0 E5 Q$ o$ Y
  119.                                 });7 z6 z+ L4 `5 L
  120.                             }
    - I, U* r. M* {4 F6 C2 m
  121.                         }
    + h2 n, \) l! n* A: C  y6 L( g
  122.                         catch (Exception exs)2 y# x; p  S  l+ `1 `/ b# T% j
  123.                         {: t1 N" j$ k8 q% g, m7 K5 K
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息4 }; r: e% h# A8 d& M7 I* G" v- X% f
  125.                         }- U8 f9 Q( w5 G2 {2 z: s. i
  126.                         #endregion
    % O, C- O. w# o% }2 A% q* d
  127.                     }: T; u5 }, P$ I4 u$ @+ L7 W
  128.                     else
    1 S' P$ ~/ L* P& o  [) V
  129.                     {: x& f* I; e1 S0 Q3 ~% o- l& W* e
  130.                         break;
    ; X; J! B" l- m5 S" k$ u  b, `
  131.                     }* j% G! D) W  m
  132.                 }//while end; ^& X2 l  }9 q4 D) g8 j( e# t) v
  133.             }: a+ ?+ [. X, a# @
  134.             catch (Exception ex)) p+ L& {/ D' F) E8 a9 x. _
  135.             {# r5 C2 u6 |9 `- k- k/ i
  136.                 //整体异常处理
    ; f+ U, U, f( T5 ?5 K
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);. I" d+ L% V3 |; i' K
  138.             }
    ( ~& Z3 V& R& ]8 l5 G
  139.         }
    . @3 B+ q6 y% L, `" X
  140. / w8 b2 b$ N4 [! X1 [0 V# F$ T

  141. * \3 @5 c. i2 \
  142.         public bool IsReusable* Q- G% U* R2 `: J, ^; i) Z' ]8 `+ Q/ c
  143.         {
    2 s: B) W" @5 ?
  144.             get
    ( n9 ^1 j$ t! j) c
  145.             {
    6 W% S# J8 m$ d0 Y
  146.                 return false;$ e% R; `8 h& n$ d: U% U6 Q
  147.             }
    ! q0 W$ D, a; ?3 y! y/ ^0 G
  148.         }* j; g) ?- `9 J) m( m3 r( W' n
  149.     }1 F) x; C) X9 c
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

* o, l; g9 ]# J% n6 C+ p% n! i
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-12-22 14:53 , Processed in 0.125935 second(s), 23 queries .

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