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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

8 h7 o5 R1 E3 c9 n
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    ; y# \7 g& e. ]: j2 p
  2. using System.Collections.Generic;  Y$ `/ G, k8 }( Z, [" m  G( H% H! Z
  3. using System.Linq;
    % H& U8 o) J5 E$ f- s3 k  ~' L
  4. using System.Net.WebSockets;' U5 N1 C5 C2 C7 B- `7 S* W. ^
  5. using System.Text;# o. x1 [: d$ Y5 p  k! K
  6. using System.Threading;
    6 w' R7 }5 k6 w1 Y' Y; L; G/ {
  7. using System.Threading.Tasks;# d6 c" p9 d0 D1 Z
  8. using System.Web;' {$ o" c7 b1 b- v; A  M& y' }$ d$ [
  9. using System.Web.WebSockets;8 e8 a& o7 j( U

  10. + [* T( H& d; S6 f4 l' J
  11. 0 W" S/ ]0 s  ~2 d& m5 X: N: x0 n
  12. namespace WebApplicationWebsocketHandler
    . x$ n8 r5 _, x" k( K
  13. {! ~: _8 k! L4 B
  14.     /// <summary>0 h8 u( w- O( y9 i
  15.     /// 离线消息  P- q4 N. j( `1 S
  16.     /// </summary>
    7 e; [- u; B/ Y( {' |+ ?
  17.     public class MessageInfo" J1 H1 H) F1 x' K! @  ^
  18.     {
    ; H: p, C7 H% X  M( m
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)/ ]6 h/ b4 l' k9 R$ v) c1 f
  20.         {
    2 W4 P3 ~; H( g4 g
  21.             MsgTime = _MsgTime;
    ' F4 t/ Y6 n5 z+ y6 g+ d
  22.             MsgContent = _MsgContent;# ?/ o" @$ ~1 j7 @2 E
  23.         }
    8 }! X5 C' v8 }: Z9 o
  24.         public DateTime MsgTime { get; set; }7 Q! v. j5 k. |' @' _7 F9 n  `
  25.         public ArraySegment<byte> MsgContent { get; set; }
    4 R$ @- T! B( G; j5 ~
  26.     }" z' `9 d* u) n4 T0 }* q
  27. 2 w  r3 L! J* Z
  28. & |' Y9 q2 B( ?0 _: j8 z. ~

  29. ! p+ |7 G8 i2 f, m! a

  30. ( {/ H1 `+ M8 S0 k
  31.     /// <summary>
    7 |  h7 H1 C: t6 p; V1 l
  32.     /// Handler1 的摘要说明, V3 C/ i. d' n4 A+ q7 U0 g% y
  33.     /// </summary>
    . D& H, J" \! [- I, G- e
  34.     public class Handler1 : IHttpHandler' Z7 Y- {& ^! Y) r9 l0 d3 e
  35.     {' ^) N' `! f8 X: L/ W. N8 F. ~
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池  _0 M; K8 z& ]1 w7 ~) z3 d5 y
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池% A0 t$ y* J* w, q
  38.         public void ProcessRequest(HttpContext context)* i' x4 ?8 g/ ~% V6 S7 C: {4 O
  39.         {
    5 |: G8 L8 z6 c- X7 o
  40.             //context.Response.ContentType = "text/plain";# m0 f4 Q1 u- u1 w3 c' [) K, l
  41.             //context.Response.Write("Hello World");
    3 J- v$ W+ O4 N; b; }+ u+ I( g; l
  42.             if (context.IsWebSocketRequest)1 L# y& f( c# y# o# C$ g1 V
  43.             {
    3 b6 M2 T' b- e% Z9 d6 S- H% R
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    : A3 X7 e" x3 S& ~- R& O% C" ~. b# S; J% [
  45.             }
    ' V. `9 E& V0 V) [7 u
  46.         }
    ; }# k2 b0 L6 p! p6 v  V

  47. 8 V4 a% R+ R4 c5 o% ]
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    1 g7 o8 f7 y  S  L- `; {" ?
  49.         {
    - s4 G# U7 [0 U* o! {; |+ }
  50.             WebSocket socket = context.WebSocket;) p& P7 I$ U& t) Y4 f! P
  51.             string user = context.QueryString["user"].ToString();. W9 I! Y' f6 N9 u
  52. 8 q2 I: g$ e) H3 y1 o) O0 _
  53.             try* e+ K4 W% b! P0 K( e# b% _/ s
  54.             {- N/ j6 E/ x' v  a
  55.                 #region 用户添加连接池
    ; ?% F7 J* i" W( s% B; n/ o
  56.                 //第一次open时,添加到连接池中
    8 x! H6 X  d5 K& s# Y  h
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    0 @) {4 V4 Z" i! y; a7 M
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加* j% g8 J4 t. b( U  ]+ w$ g8 U
  59.                 else( w0 e$ U% H. X& D
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    % M% R8 P' E9 v- g5 D( Z! D. u
  61.                         CONNECT_POOL[user] = socket;# A* y4 f% h; @; E* i! ^
  62.                 #endregion
    $ Z! ^. x: c) a5 P

  63. $ `3 d& z5 A+ j- z
  64.                 #region 离线消息处理7 q% \# O" b; M+ F5 c* J2 [$ a- f
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    " y1 u) _9 X$ L, y+ n8 ?7 N
  66.                 {5 ?8 f( V5 [/ |# X3 y" l7 _
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];, Q7 Y) w5 s9 `4 R
  68.                     foreach (MessageInfo item in msgs)
    + a# v8 w" f  \9 Q
  69.                     {
    1 U, U. ?* A+ }8 d" u
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);: q# M7 I0 E' k8 \
  71.                     }: L1 ~) q# n1 L" l
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    : ?, G- y) K" r5 a- h7 U
  73.                 }  J* {( @4 I4 s8 D& f
  74.                 #endregion1 A9 \& h( {7 k4 ?* D( P

  75. 3 f* o! z, H; ^. E( D: ^9 F
  76.                 string descUser = string.Empty;//目的用户9 |6 w. J) v" K
  77.                 while (true)$ B' S  e9 [$ I% K/ e/ i- N
  78.                 {5 ~6 x# W5 i) @0 C( f' u: b
  79.                     if (socket.State == WebSocketState.Open)
    $ b! X2 i8 O) H0 D0 R$ {- v
  80.                     {
    5 D+ \8 i4 L# n8 e  A" O
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);+ o& y* {5 I! Z$ Y
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    6 E4 R; d# e% v+ N0 m
  83.   c" F/ H5 x1 x6 o0 l
  84.                         #region 消息处理(字符截取、消息转发)
    8 V1 K1 H6 y0 u$ t2 F
  85.                         try" d7 m# p: `1 f/ {' ]& K
  86.                         {
    ; U" w3 B8 A  g) j- g0 x' s
  87.                             #region 关闭Socket处理,删除连接池
    + f- T8 a9 j& D! P! `
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    : v# O$ j3 g* L+ g0 z9 g
  89.                             {
    ; C/ ~- k6 M7 ]9 B2 L6 Z% k
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池8 w0 c- t4 @# z% `7 u
  91.                                 break;
    3 B' U0 q0 D# S- g9 m
  92.                             }
    6 f0 ?" g  y% n* G# \- K
  93.                             #endregion
    4 l; Z/ m* P5 S

  94. ; d1 u3 M" Z  @+ R0 c/ B6 p$ [+ O
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息3 K1 B" I" q% |8 M  `! Z4 |
  96.                             string[] msgList = userMsg.Split('|');
    ' S4 v. v/ }& ~% v) F" i8 `; A
  97.                             if (msgList.Length == 2)
    1 l. K! G0 k' f9 y1 B- `2 r
  98.                             {; F3 o4 G; W$ W* \
  99.                                 if (msgList[0].Trim().Length > 0), Y8 O. q# z& e' D
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    " @  A9 A6 w0 ^# M  e% y; l% i6 `
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    ; g$ E$ G. ?+ w: ?
  102.                             }+ `: w# J) Y* v8 v9 [) P
  103.                             else( E. n% k, p5 F7 i" [6 h
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    ' a5 ~' P2 e# t1 R/ k# P! N8 Z

  105. * y. N0 R) }1 a
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线$ C7 c% ^/ d& l, H  f, n
  107.                             {3 w: w* y- H& V9 W" Z! n4 Q
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    3 |7 l* U! ^* }& c/ `' G5 k+ P
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)6 W2 S, y- U0 s( s! M2 H4 p
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);( L7 P: r+ w8 }% `0 x) s& Y
  111.                             }* y, D) g1 J+ G' d$ X. a9 l' E" r
  112.                             else
    * u+ d7 O: B. n: p( X
  113.                             {" n! K% K4 C0 _
  114.                                 Task.Run(() =>
    : N6 [$ r/ x! ?8 ?: h' c
  115.                                 {
    ' j1 ]) @! Z  z# N
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中4 F* i/ F% d% b) I
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    ) a# b: A: K3 K6 D/ f4 c
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息' k0 z  @1 H: c6 a$ k1 j1 A
  119.                                 });0 k: d% I* r5 V! Y' q+ P
  120.                             }
    % u+ H9 R# m  G: ]5 j0 s& D+ u
  121.                         }
    # W4 i, E3 S9 Z. J9 X4 W  g
  122.                         catch (Exception exs)" V7 d* a- V- x" Q# X7 J
  123.                         {
    8 E- N  }3 ]6 Z5 ]( p3 w, {
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息; r1 g! W/ _* N' k8 A
  125.                         }
    1 m1 Y( i- W8 V, W+ J, F
  126.                         #endregion
    # J6 W& e9 ^% Q' @  ~
  127.                     }" u2 R9 h: h* u  ]0 P+ z
  128.                     else
    # E# h( K8 A" L, f8 m) C) Y
  129.                     {
    - f* t. P: h- D8 }. H2 D/ ^  _
  130.                         break;8 k) b0 z4 |5 `8 d3 H+ Q4 H
  131.                     }
    % x' `- g9 f* }1 y  a( P5 p9 q
  132.                 }//while end
    . K0 f. P& w4 k- `; j- V
  133.             }
    ' F- B$ ~. [* m5 z$ x  `2 g: N, |
  134.             catch (Exception ex)
    1 \9 D! y3 P# f+ e  e4 }
  135.             {/ _8 R# b. E# {- P
  136.                 //整体异常处理% }1 J% B: D+ v5 Q/ L. d
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
      j* e6 _5 g( y4 h5 M
  138.             }
    8 `% J3 n1 h5 d9 i& S' C6 {
  139.         }9 L7 S4 G$ |# h) T, b
  140. ! g; F0 l, t3 y; P

  141. * W3 J) u2 N! ~& n# O, Z, h- |0 J
  142.         public bool IsReusable: M: @9 N8 B6 b  e, _2 Y& B2 |
  143.         {* b: n2 f  H1 p& j9 t
  144.             get& i& B9 o, M, R# O; B4 ^/ t
  145.             {
    . y% j. b  E2 F! y& N- C
  146.                 return false;' D- M  Q* }$ `( m1 o
  147.             }
    & W, D$ Z7 v, u" p% {
  148.         }
    * M9 _8 a3 n$ h8 @% o
  149.     }$ b# x! Y, {1 a* G3 }
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
3 w' d* J7 g$ S' [/ g, g+ V
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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