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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

. R' g$ T1 ^, u7 u) W5 \
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;/ E' m& w' g4 V% ]5 Q4 N$ _# Q
  2. using System.Collections.Generic;
    4 K' f. U% m# L+ i) j% l
  3. using System.Linq;
    9 h2 ^' l; n& C  N+ m1 T7 H- V
  4. using System.Net.WebSockets;
    + d- t+ Z" i4 ~3 r% b
  5. using System.Text;
    ) U$ I' ^( Z3 Q# W4 q9 ^
  6. using System.Threading;  R0 {* y2 [9 ]
  7. using System.Threading.Tasks;
    1 m: x/ Q9 ^+ V& @+ t; @* y$ E
  8. using System.Web;
    6 x  t# I  k  y! v, A! V5 g
  9. using System.Web.WebSockets;5 F6 E1 o7 I( Y' i
  10. / m% B2 D0 O! W

  11. " G+ P5 l/ Y1 R0 A
  12. namespace WebApplicationWebsocketHandler
    . x) N4 T# j1 M% r  @3 S& x
  13. {
    / S# {2 D) Q( V, [& }6 A7 U" x
  14.     /// <summary>
    3 A1 b+ i- b$ o) P
  15.     /// 离线消息( Z  A6 h# r' g) v# k
  16.     /// </summary>! O5 ]9 t: {! P+ Y( f
  17.     public class MessageInfo
    3 J) U& N, L# I, f- y! n
  18.     {# ?9 r' }! R3 ~: D0 y0 i2 j: B( _
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)3 _  z' s" @+ k3 v% t1 l
  20.         {
    4 W+ n/ i: C  ~/ ?2 S. d. Y
  21.             MsgTime = _MsgTime;( a: H+ S1 H: H/ i! Q
  22.             MsgContent = _MsgContent;
    $ I; U2 l$ o2 y2 F: n
  23.         }. O9 O# o' Y( {; ?4 Q
  24.         public DateTime MsgTime { get; set; }
    5 ]+ q* @; p" l1 o8 Q4 ]
  25.         public ArraySegment<byte> MsgContent { get; set; }' T8 f( I7 ~- B" y8 ]
  26.     }
    # W# V3 L8 j! N" w4 @  w. L

  27. ; @: a# A8 |7 W2 _* D' _+ k: ]! Q
  28. " B) R* m4 q/ U
  29. $ Z2 j: Q4 b- s& ]! n$ g. L) B; v
  30. 4 p0 X) F# ]9 q. {
  31.     /// <summary>
    : Z" J- Z  Y; _+ r9 Z) h
  32.     /// Handler1 的摘要说明6 u( }: A4 ^( S3 p% ]0 X6 \
  33.     /// </summary>
    # l5 _2 _2 N5 \, G
  34.     public class Handler1 : IHttpHandler
    0 s' J/ @: J* y8 u
  35.     {# J' ], B$ V( v& \6 K4 h2 L0 D
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    , F" z( Q) v# J1 E% C1 i
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池4 H/ w5 G( u5 H1 Y! X
  38.         public void ProcessRequest(HttpContext context)# ~) {  {' ~4 I+ A1 V! ]
  39.         {
    ! y$ x7 p9 T2 X: q+ Z
  40.             //context.Response.ContentType = "text/plain";' e! S! d9 t; G% D. I
  41.             //context.Response.Write("Hello World");
    5 X0 @  Q1 k( _# _
  42.             if (context.IsWebSocketRequest)
    1 F/ U8 p+ L0 V; ]+ H. y, n3 A, e
  43.             {# Z  D3 P/ o  B- n6 Z% {
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    1 v8 P# w9 T' x8 y1 w2 ~$ ]
  45.             }
    6 q  t3 B$ R/ X0 R
  46.         }
    * C! M! M% T4 ~8 A3 v! D$ d

  47. 5 X' u1 {. n, \9 C" g% X# s
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    % N) w( }: T( u1 ]+ v! f1 i$ \9 f
  49.         {
    0 E( U; j7 A$ H* N0 _( G4 Z' `
  50.             WebSocket socket = context.WebSocket;
    9 e5 U1 @% W' Z: L0 z# y
  51.             string user = context.QueryString["user"].ToString();, n7 \+ J7 w( W
  52. ' H$ o3 e: V7 d7 l) t. U
  53.             try! T1 R0 m0 K1 V+ V: |
  54.             {* S4 N0 i4 b* l6 u
  55.                 #region 用户添加连接池: _+ u" y4 Z6 b  s1 ?  y
  56.                 //第一次open时,添加到连接池中
    / t6 N5 A9 e1 S: ~. s
  57.                 if (!CONNECT_POOL.ContainsKey(user)); B% E- D% j% {8 K5 e+ s
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加0 Z  d4 \: j  D2 M& }4 N5 a3 I
  59.                 else$ K5 V  a, {  w1 o, L
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新) d5 C0 t& _. y
  61.                         CONNECT_POOL[user] = socket;9 F, b* ?* V! ]5 S1 V. G3 @
  62.                 #endregion" n- M- y6 n" S- L% G. G) q9 X

  63. ' G1 O& ]! J/ P
  64.                 #region 离线消息处理
    8 o9 l9 J- f. W" e
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    & p! {/ O, d5 N! U
  66.                 {2 z/ F7 e+ r/ E; y
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];. s, X. s! A2 `% E+ t9 E
  68.                     foreach (MessageInfo item in msgs); g+ v' l* }' ]( L4 T% ]0 C3 \  d
  69.                     {
    ' ?; v% U8 L, ]+ X' [* {
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    ; p. ?: _- Q6 f; v9 T$ g( X& g( D& u
  71.                     }
    6 {8 t+ L9 |% C: x
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息* {! K7 J* P- r% X0 j7 U
  73.                 }* w( [' V& ^0 x. ^" R
  74.                 #endregion+ @& a1 A4 ~! `; f! e

  75. 4 x0 h: I8 g" Q- T: i
  76.                 string descUser = string.Empty;//目的用户4 k, Q/ W! K& F
  77.                 while (true)
    " P  O- e4 P( ]5 g$ m
  78.                 {  g0 s2 n  t9 d5 Y$ ]6 L# K
  79.                     if (socket.State == WebSocketState.Open)
    # p# O, s. ^; f$ W4 }
  80.                     {1 b5 M4 ]/ o" X6 w" }
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);) m, E& n6 r: O& U$ x8 P
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);4 v) j% v/ e) q$ r+ n, C9 v
  83. # x: k2 m3 A5 d6 r
  84.                         #region 消息处理(字符截取、消息转发)4 {% x* ?) ?5 k8 ]9 Z( R
  85.                         try
    % t. c  X: |; L& L* t
  86.                         {- ]0 Z8 Q5 O3 G7 ]1 n6 Z1 k
  87.                             #region 关闭Socket处理,删除连接池
    , `1 A- k1 G- ^% [
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    % Q: \- T8 e6 u( o1 Q# \8 E1 z
  89.                             {; L5 H% W0 [& O  j0 B) c  P
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池" u9 B$ f" n" C6 W0 ^
  91.                                 break;. }1 I. o. f; N0 k6 |* A* m
  92.                             }2 g, `5 n" v; |+ s1 }, D
  93.                             #endregion
    1 K: Q7 x- o/ v& w% C7 V6 L2 b

  94. 1 P/ b, n5 `( W" e
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    2 ~2 f! _+ Z7 D* \
  96.                             string[] msgList = userMsg.Split('|');
    3 P9 D& J$ U2 y# E: ~8 w; b/ B
  97.                             if (msgList.Length == 2)
    1 R0 d8 W1 ]/ V
  98.                             {+ j0 j+ T1 k! g4 B8 [
  99.                                 if (msgList[0].Trim().Length > 0)
    , P1 U8 @+ O! l) O% m! b5 w8 }( z# }3 }
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    8 @% N" ~' {9 e- f! }3 @: M
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    4 Y) ~  Q1 ?* X7 [7 ~
  102.                             }- V3 N  f0 s* m% j$ O2 D' W
  103.                             else- \" z" l: K; x$ C3 n. T
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));$ ~- t3 U- g% Y5 J0 a
  105. 1 M3 f; m7 r9 v. ]. U' ]" f
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线" I. |5 T2 @' a4 D0 k! p
  107.                             {
    . n) x0 T, I$ B3 {
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端1 g0 a/ h: Q1 N2 [: c* q. s, L2 p
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)& g/ Y; F; B2 K- S
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    2 q, d1 {. L1 K8 S2 f/ E
  111.                             }8 r2 h( f) }2 ~
  112.                             else; L9 `/ p& T/ C3 j  `# {
  113.                             {
    / i5 Z7 E/ D+ N( o
  114.                                 Task.Run(() =>& A9 b, h' a. u
  115.                                 {- a9 h1 f+ z  r
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中4 h4 W- d# f) H- q0 [) ]1 Z
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());4 z2 [3 q  V/ T, M( u3 ~3 ?
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    8 B6 q& x+ L6 c
  119.                                 });
    , p' k; B/ O3 j; i
  120.                             }1 m/ O% q! v+ Y: Q* D
  121.                         }7 k$ X% C, `- r& z  Q7 q% s
  122.                         catch (Exception exs)
    7 l+ F- |2 z# ]$ \+ t/ K- e& m
  123.                         {
    + R) V! ]# u6 \. e1 p1 t# d% C9 c' d
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    . k- p8 d' e, c( n
  125.                         }
    . O( N7 k+ \9 S# f- K
  126.                         #endregion, I$ e1 N5 y' U2 {. I) R5 t: s
  127.                     }9 z& I9 q" g% p% h( O
  128.                     else2 P( C+ `: G6 }7 v- I
  129.                     {- _; w  T& K3 h' R0 \4 S
  130.                         break;8 c9 \) F/ ]/ _5 o0 G
  131.                     }# o/ o! X, a! R, G& y
  132.                 }//while end
    & r. t; G( o  n" Y
  133.             }
    5 V( ]. _- c- c2 V' h4 k
  134.             catch (Exception ex)
    $ p, f( l% \/ S
  135.             {# r' l8 P% q# t: w' d1 l& c
  136.                 //整体异常处理8 Y' t( \6 i. q7 N/ x, v
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
      z! ^! x- k! F  n
  138.             }8 S+ c+ T' {7 |- w8 T# e
  139.         }
    : M& i6 J8 g( ]# _9 H
  140. ) S0 m7 @$ e0 q/ A
  141.   D4 f# W, y0 |
  142.         public bool IsReusable
    * H  x: ~* ^  ~
  143.         {
    ! \/ d$ ?( B- D1 w
  144.             get* X0 ]5 H) c* q* U$ |; e  }
  145.             {* @! `9 H: C8 j" E0 I4 x4 J! q% A
  146.                 return false;$ V. g- U7 L  l$ x
  147.             }
    " Q$ m) W3 q3 l* o$ }# b7 X: H2 w
  148.         }4 M& E/ k3 {! k+ w# R/ l$ N
  149.     }. v& {( X$ f' s% m& g
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

) ]% X( M$ n' B0 V- E( n6 c
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-6-20 00:01 , Processed in 0.058683 second(s), 22 queries .

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