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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
  z- z3 v2 N$ `* j8 h; d# X
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;# u- t( l2 a, g2 l
  2. using System.Collections.Generic;
    3 D3 ^8 b" F% S' K* P+ R
  3. using System.Linq;
    ' |" D0 N" r, g4 k0 O. y( a
  4. using System.Net.WebSockets;! _$ T+ l# _( Z/ Q  h
  5. using System.Text;
    5 W: u' s; i0 Z- n
  6. using System.Threading;! V" C) {  f5 b0 q; h' W& ~: F$ V$ \
  7. using System.Threading.Tasks;9 d; `5 O5 I$ F$ e, Z
  8. using System.Web;
    # C) l' e* w2 N) p
  9. using System.Web.WebSockets;
    ' D# @. V( I8 U: }  ?, f  s& W4 M
  10. 3 J! L4 ]9 [1 [$ }$ w# C

  11. , }. B. Y7 B& N
  12. namespace WebApplicationWebsocketHandler" Q! p; o0 P, P* ?8 J* @, D# s
  13. {
    $ d, \0 c$ A4 g' ~
  14.     /// <summary>
    $ e8 f# {2 W2 _7 `& o( l) J
  15.     /// 离线消息* i, S& _4 X9 f! t$ e9 t0 r
  16.     /// </summary>; h4 }( Y; ]9 Y+ l+ B) K* I
  17.     public class MessageInfo
    8 e& {  U- z( n% N6 s$ M- Y
  18.     {  q1 i' J. E( J9 E3 W, a6 w
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    7 T. e5 w! v4 }. O4 Y- T5 i
  20.         {( _9 p8 q! L+ f; N4 p
  21.             MsgTime = _MsgTime;, {) `, v) H' e: U/ I$ B
  22.             MsgContent = _MsgContent;
    1 d8 r7 \  m: m7 U; I) z% Q- _- }3 N
  23.         }
    4 @- l( t% H8 ?& R/ [
  24.         public DateTime MsgTime { get; set; }7 V/ j6 v0 w+ ^3 s0 i
  25.         public ArraySegment<byte> MsgContent { get; set; }
    - R% F9 Z) x- I; H9 Z3 ]
  26.     }
    4 H. D' a; f4 U

  27. # q* ?& @" @. S' D9 S" H# E$ a
  28. 9 c) R) q; Q8 L) |) x  ]1 a9 L

  29. " y0 G1 q6 @3 |; E, Q/ _% a

  30. + M2 E% n* Q3 G6 D% K& c2 w
  31.     /// <summary>' k( f" j' |8 g5 p) P: ^5 p
  32.     /// Handler1 的摘要说明! e- y- O+ p# o6 H+ x" J% H
  33.     /// </summary>
      L1 Y8 M+ i# V0 x
  34.     public class Handler1 : IHttpHandler3 \* X$ f) ~! q! C4 y
  35.     {$ h: h9 {) h4 j( `) U
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    . N# {; y# l4 }- l- `6 Q) Z
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池3 ?: u1 f" f+ x
  38.         public void ProcessRequest(HttpContext context): x+ G& K6 V. [
  39.         {
    & H; i1 V2 X; n# F6 g* s
  40.             //context.Response.ContentType = "text/plain";7 Z$ h6 U2 U7 ~; B4 c7 W
  41.             //context.Response.Write("Hello World");
    5 k' G' D( L# Z& v1 g2 ?0 d, y
  42.             if (context.IsWebSocketRequest)
    9 d& W8 j* D  o/ Z$ b
  43.             {
    / Z& M) W2 ]$ i5 D* y
  44.                 context.AcceptWebSocketRequest(ProcessChat);5 i- p6 m8 A! R2 G. q
  45.             } 5 U2 k9 p, [5 \' T3 r/ \  r2 V
  46.         }
    * l: b0 n3 `6 A- k
  47. + o! o2 w/ M1 F" }
  48.         private async Task ProcessChat(AspNetWebSocketContext context), x+ {* j! C( h/ ]2 o
  49.         {1 k2 h3 O- e0 S$ y5 H
  50.             WebSocket socket = context.WebSocket;
    ) p0 k" }, f" O1 n
  51.             string user = context.QueryString["user"].ToString();
    7 q* v; i4 ^7 x) \. ]

  52. 8 d1 B7 Y; x* C# @& @
  53.             try
    5 u+ E* I  C8 B* D$ v
  54.             {# ], S) a" b$ {( ^/ o
  55.                 #region 用户添加连接池
    $ ^( K1 s: R6 t0 r  \
  56.                 //第一次open时,添加到连接池中
    7 Q& M6 `/ {- K  b' I& P1 g
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    5 u0 e/ C9 h! S
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加2 @! O( ~2 J2 J3 V
  59.                 else% g+ n- f; y3 W6 V4 U* N4 R" [' _
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新: b7 U7 W% g# n! P
  61.                         CONNECT_POOL[user] = socket;* V0 Z; R: P7 k' S7 w
  62.                 #endregion6 n' l! a* Q- z3 W: ?% b) Q2 Q
  63. + C+ I" v6 `, z3 g1 w' `, y7 _
  64.                 #region 离线消息处理7 h4 J5 t0 _3 `& _& `3 ]
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    & U! S9 b0 S' e' I& r
  66.                 {$ T3 }* i; c  E' x
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    ; l8 ]" [* v3 e7 J$ N" T
  68.                     foreach (MessageInfo item in msgs)
    9 ?4 }* K+ d# \5 k- ?8 T
  69.                     {
    : G8 Y! N0 r/ O& L6 ?
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    9 H2 p( s  Z' h* f  L( }
  71.                     }
    3 A+ Y, n3 I! e( Q& L
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息/ \# P/ G3 h# b1 m1 o( `+ ^
  73.                 }) d' o. P! J/ J3 P& ~, E/ T; [
  74.                 #endregion. n' m  G- n$ W1 S# J: |: J
  75. $ v6 ]- e1 v. O2 E
  76.                 string descUser = string.Empty;//目的用户, o  ?) E5 K+ E3 W
  77.                 while (true). `! J& A( j0 j, X( F% Y
  78.                 {& F) c. k/ A) @8 F) O; m# Q
  79.                     if (socket.State == WebSocketState.Open)
    0 A- q6 S4 X1 _! v! [* _5 B# f4 {! H
  80.                     {
    * J! P9 [/ s5 e
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);1 o  X: e" o, d* L4 }8 c; \
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);: _; e7 d. k% G: N( g

  83. 6 }- @' Y0 ~) u7 o) K
  84.                         #region 消息处理(字符截取、消息转发)' z( ~) `+ P" Y" c0 e  d& X1 i% z
  85.                         try2 |& K; I4 F! F: x9 L' r
  86.                         {1 _+ b* H# N, t% N( ^
  87.                             #region 关闭Socket处理,删除连接池( g$ G) x. S7 ]
  88.                             if (socket.State != WebSocketState.Open)//连接关闭2 h2 }+ b4 |4 H9 x& p6 e  `: a
  89.                             {+ J2 ~% ^2 H- j& h/ H
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    1 C, n! v. G9 b7 U! i% w: j: b
  91.                                 break;9 ]! s& E/ [& H& U1 n
  92.                             }6 e- `4 M& S" D0 p5 _
  93.                             #endregion( a$ x' N1 {0 p+ G
  94. . k8 M' D3 _1 @. E3 Z$ L2 t5 V
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息; j/ t& Q- J! b' ]" j, k- C, b
  96.                             string[] msgList = userMsg.Split('|');, j; T# o5 _7 n3 r
  97.                             if (msgList.Length == 2)& k' \7 y1 s4 G. ~
  98.                             {
    : F: n+ o% [/ ?; J
  99.                                 if (msgList[0].Trim().Length > 0)
    5 K0 _2 [* ~! d& e3 ?- ^
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户7 z, h- j5 g& T' Z/ H  u
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));1 M2 c1 T' }- ^- s
  102.                             }9 C* y- y9 A, K+ ]5 r
  103.                             else* w! M2 L) |* b/ L: ~/ G/ Z8 H
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));6 o1 v# K) c& n: s3 U2 d0 O

  105. 7 h$ w: [' M4 @" F: q
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    & s1 ?6 N+ ^: E7 i
  107.                             {
    % g* g- ~& Y+ ?& d3 ]: ^6 G: ]8 k
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端8 z  v' Q7 p. g4 B6 Z5 a+ u9 F
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    ! }( h2 m, d; o6 M% m/ T
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);" b, O$ t# ]/ b" W: `
  111.                             }' S; v  l1 K/ O9 k
  112.                             else
    % l/ z/ I( W3 z. w3 q
  113.                             {4 L, T0 p/ S7 P7 z
  114.                                 Task.Run(() =>% O8 {- s3 ?5 j
  115.                                 {
    / N  t  o7 E5 c% Z
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中) f0 X3 I' H- L! E0 ^
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
      ?& ~3 w% U) _) C2 H4 j( S) S; \
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    6 Y+ i5 _- d  }3 u& w- p6 v# B
  119.                                 });# g' t) X. z4 d" @) ]+ |
  120.                             }! g  d/ a% _7 {4 P4 ^8 y
  121.                         }3 I0 q: _# F. v. ?
  122.                         catch (Exception exs)8 q4 G1 J, l) _; ]( a9 \0 |
  123.                         {& [6 g0 V& y0 V. @& d; l+ B
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    8 s; R4 o4 t# e6 ?4 H/ }$ a) C
  125.                         }
    0 L5 ^0 ?( ^" l$ Z
  126.                         #endregion; z  K- s3 w. O( D
  127.                     }: m. M" Y8 j7 ~2 `/ P* X
  128.                     else
    " o5 M; q3 e, g/ ^1 V
  129.                     {
    ' @% M7 g* E# |+ [9 S! A7 k# W
  130.                         break;
    2 w/ F9 \, f7 k: |6 n5 A
  131.                     }
    5 q, K( S/ ], _- R
  132.                 }//while end
    + j4 F+ _, M. d' y4 f
  133.             }
    1 E7 F: o* o) ?) O  L  |; Q" C
  134.             catch (Exception ex)% @$ z0 @( P& z( k; t) c3 o' U3 @0 b
  135.             {7 n. _; `1 v# Q$ r" u. V0 f
  136.                 //整体异常处理
    1 j; j1 [  k. D. \/ F1 g
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    7 D3 B% {' i2 i6 E; l* e
  138.             }7 n3 }: }0 u+ C3 J2 z8 `
  139.         }' P+ ~! R* f1 \* ^* P4 }

  140. / y1 |: k( r3 w
  141. , ~) ^6 R; H! U. S# M8 O
  142.         public bool IsReusable4 P" @! t9 F  d
  143.         {5 Z' r, Z8 z/ j6 {" h5 _; N
  144.             get
    " W1 c2 H5 D: L  W7 {5 _/ q
  145.             {- Y) ~6 V5 ~8 {$ D* t: t: m
  146.                 return false;! e* z' {+ m0 P. I* P+ @
  147.             }
      f9 k- l, o% C
  148.         }* q4 S2 @! f) }! |% w
  149.     }  Y- u' x5 }  n6 o6 g" S& [
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

, ?' J2 }0 d( p2 `& P9 `
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-17 15:44 , Processed in 0.161046 second(s), 22 queries .

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