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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

1 \5 b  C; S& x6 x, r$ p5 N4 U
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    % L! k& R' b3 L0 O; {- W% B  ]
  2. using System.Collections.Generic;
    - }* i9 U5 O% R9 ^& O' S) R
  3. using System.Linq;* L5 e1 d/ v# z! M; S. I3 e- {
  4. using System.Net.WebSockets;( M5 {8 j" h$ t  X$ I8 E5 f" ?
  5. using System.Text;1 _4 `5 z) P- u! W0 ~
  6. using System.Threading;
    # T: J( e9 f. _5 _
  7. using System.Threading.Tasks;$ Q9 O1 |  I! p7 n% H0 A# }
  8. using System.Web;- X. P, X& [- }0 Q& P2 {
  9. using System.Web.WebSockets;0 V. G0 H# W  ?" V, `9 t1 R* R
  10. 6 K$ v' V2 L, C" g

  11. ( G( P" N9 f4 `/ }) A4 y1 `( J
  12. namespace WebApplicationWebsocketHandler
    + ~. `. i, I; D9 v7 x0 i  a3 `, B' A
  13. {% e" o; b0 P: P! o) ~3 B! C$ ?. Z
  14.     /// <summary>
    7 e# p" [( {. U4 V
  15.     /// 离线消息
    ' Q* |# _; Z- E# X; n4 O- n+ J9 _
  16.     /// </summary>
    ; A0 ^6 I. r$ W5 r; `5 ^8 N
  17.     public class MessageInfo1 }4 R, Q+ n# `! Q: F$ x/ l) `
  18.     {
    ) b2 D5 O& X2 n! p
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)4 x- x' P( h% `: P3 w0 a
  20.         {3 J: {* l  M4 s
  21.             MsgTime = _MsgTime;6 P+ r2 v  F, l9 E1 r
  22.             MsgContent = _MsgContent;
    8 D) \* T. u0 ^1 m7 v- {+ u1 |
  23.         }  {7 `/ m+ O& x0 |& u* j
  24.         public DateTime MsgTime { get; set; }/ w& D( @% p4 b2 d  J9 d3 I9 e, t( v6 m
  25.         public ArraySegment<byte> MsgContent { get; set; }
    & h6 g5 ~) D+ n2 ?0 @5 p
  26.     }; z9 e+ w2 k( i
  27. 9 N( X# [. R+ S) C: b' z* d# ^. H

  28. * _! ]; Q! F' [% t3 u+ ~/ f) I
  29. $ t7 G  d) _2 `! b* n# ~6 ~9 \! s

  30. : k  N$ C! q# T' x/ d
  31.     /// <summary>
    4 \, q" H( a) E- W
  32.     /// Handler1 的摘要说明7 l) O8 U5 r  F; @5 r. H
  33.     /// </summary>3 O4 h! @9 P, o" o, `
  34.     public class Handler1 : IHttpHandler# k! F5 E# R- e* Q; E
  35.     {* ?( b1 X/ \& ^! D: a2 R8 X
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池$ r) y6 ^$ @- W) y# ]
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池( H# D* h; [& x& \
  38.         public void ProcessRequest(HttpContext context)( ~/ p3 o# F2 ?3 W
  39.         {
    7 t" s6 ?) a; M) I
  40.             //context.Response.ContentType = "text/plain";) U% C0 T- G0 X6 m5 H
  41.             //context.Response.Write("Hello World");7 y7 h0 [4 J* ^7 c7 o
  42.             if (context.IsWebSocketRequest)
    ! W( I: v, S7 H
  43.             {2 t, P( N8 |. e+ q
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    ) V, c2 {7 C/ ~7 i( _* V
  45.             } 1 z% {% M6 ]2 o& ?0 H) v- v
  46.         }
    3 B3 B% Z% w9 ?$ G8 o2 r

  47. 8 q! c; u6 p" k
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    # ]% I4 f  {3 e1 g/ }# v% i/ u
  49.         {
    3 X3 |0 \# @& f: @& q( s3 G
  50.             WebSocket socket = context.WebSocket;
    * y- D  Q0 S" [$ G: C
  51.             string user = context.QueryString["user"].ToString();) Y$ P0 R- K- ~/ K( |
  52. & a3 f6 t% s( n0 |: Z4 A9 `" _
  53.             try
    ' e* j) J( y0 A; u3 u6 S
  54.             {
      L0 t8 v8 T" {
  55.                 #region 用户添加连接池
    * D6 a( P: ]7 q0 i
  56.                 //第一次open时,添加到连接池中6 Q: V  O* R8 {7 Z
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    4 m; D. c! }3 \$ @% ]) p' c
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    " }3 o# G6 {! H, ^
  59.                 else9 f+ l/ g9 X& ?1 z! R3 G
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新4 ^7 E6 H5 f6 G/ q
  61.                         CONNECT_POOL[user] = socket;
    ' Z4 Z! t. d0 R3 M. }4 H8 \  s
  62.                 #endregion* @6 S. H( z! T. _( f; n* C( j
  63. - V& o" t1 ]0 @# l; S
  64.                 #region 离线消息处理4 A2 g9 r: `" ]4 V
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    7 K9 e- c/ X7 K( {7 r9 G
  66.                 {
    " R: Q' N- @; i* }( p
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    ; D0 `1 K7 u4 H* B/ x
  68.                     foreach (MessageInfo item in msgs)% ?7 {2 v4 S% Y5 v+ k0 p4 `
  69.                     {
    + F  P" j3 h+ h. M
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);/ `% k  i" f# Z8 k, H, Z
  71.                     }
    , _6 ]( l( Z* Y: O" X+ i
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    1 J4 e. Q( R8 B& F
  73.                 }
    2 @: I; J7 H2 w! u
  74.                 #endregion
    2 F; O& s: u9 _

  75. 6 T0 `8 ~8 H9 U, U9 J
  76.                 string descUser = string.Empty;//目的用户
    ' y* D& O$ W: F
  77.                 while (true)8 U8 d# \( {9 j& \2 {: u
  78.                 {
    ; q1 n1 D1 P; E" d
  79.                     if (socket.State == WebSocketState.Open)# a1 D+ p* @) u2 v# u) i
  80.                     {3 t& U" W  L; \
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);; a  M* D) |6 p; U3 ?5 B" i* B
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);& G7 M* h; w5 u: J
  83. , y7 F* I9 d# p0 C) Q( i" T* P
  84.                         #region 消息处理(字符截取、消息转发)& c3 N/ S6 N$ R6 B3 A2 n
  85.                         try
    & H$ s& ~. g& c% P- W! b, Z3 X' h
  86.                         {
    4 `7 v- c5 A9 d1 N& Y0 \5 S
  87.                             #region 关闭Socket处理,删除连接池1 E* P! w; Y! g" V' L
  88.                             if (socket.State != WebSocketState.Open)//连接关闭/ I& s' w* `: V2 n2 ]+ V
  89.                             {) T: ^& J6 b/ A! k6 o
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    1 B! r% m* q! o, Z5 a, l: q' B) x
  91.                                 break;
    7 p7 E  s5 S" W; O7 |5 N  p
  92.                             }
    4 s+ b4 X* ^$ k7 C% {+ T
  93.                             #endregion
    . U/ B8 I! X5 @' D3 ], B2 l: l
  94. ) g- \; a8 u/ i
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    6 x# [8 u' q7 U+ W9 q
  96.                             string[] msgList = userMsg.Split('|');
    : n0 n- b1 g! o; N
  97.                             if (msgList.Length == 2)
    ' |! k" G# s4 X) R1 _  d
  98.                             {
    ( {$ {' x8 Z: Y5 Y; D, \1 T
  99.                                 if (msgList[0].Trim().Length > 0)
    ; r! D, n& V, \$ @1 q
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    $ N, {. v: r# Y; P
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));$ f( M- {) J5 a5 f
  102.                             }  }1 j# h; L. v. s6 W( i
  103.                             else; l1 K& [5 u* m) N2 M8 A
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    5 `# w5 U' j# a2 E

  105. 8 s2 ^& z0 e3 Q0 W) U1 f% i
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线/ S1 J" J$ z# a& y/ B5 {# o- W
  107.                             {
    3 \: s+ i6 i; C0 S: P  b% o
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    9 {3 [1 ]2 J1 }! @  Q9 E: @
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    ( j0 R0 `! `; u& S# @& R8 W
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    : W+ `( {. e5 Y5 ~; V
  111.                             }9 F7 I' S4 k; j8 f! [- k% [
  112.                             else  a4 y+ M. Q, j
  113.                             {* ^2 h/ }$ m. |" k' P) q' i
  114.                                 Task.Run(() =>" g* b  _; n8 ~  x9 _5 Y- |
  115.                                 {2 e0 K! Z! K! l% T. Y$ Q6 i0 [
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
      \5 v$ n9 s- e6 q  A5 d
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());; r( n7 {  p9 I, i2 e# P/ E  a/ f& J" b1 f
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息1 U6 y3 y* j: V' P
  119.                                 });
    % b  a7 @  f. x# y3 j' P
  120.                             }+ K) x8 f3 {6 L
  121.                         }- |+ G1 E3 Q# L2 U5 ?6 z
  122.                         catch (Exception exs)
    ) n) H$ C1 M! E2 ?$ c
  123.                         {
    7 l+ X. i! T( b% `6 J" N, H
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息( D: W* P7 a8 G# \* i. z" Z
  125.                         }
    ' U: n- t, Z$ x' s% Z. W3 f  R
  126.                         #endregion
    - Y0 ^0 T: E2 v1 D" _3 x2 E
  127.                     }
    2 ^, u* e. t' O, n
  128.                     else
    : E) S" N% E) m+ |: X0 T9 H
  129.                     {6 ~2 p) B! G/ a
  130.                         break;
    ' m: U/ h" A' V* E9 I
  131.                     }4 g2 x; X& n: V2 s; R' y2 F
  132.                 }//while end$ H* q# z( n8 w% E+ ?% m
  133.             }2 R6 M- V3 z4 K8 i/ f
  134.             catch (Exception ex)
    ) b/ ~. L# P1 `
  135.             {: M8 b3 u  S0 H7 k/ e  e+ [+ y
  136.                 //整体异常处理
    9 J# y  R9 v! V/ W- ?
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    ) p: \# R/ H! l9 r; T5 W
  138.             }
    5 ^( c- p0 h& v% ~
  139.         }$ h. J/ n/ W2 @/ N

  140. ! P! H$ k2 s- H' Q
  141. / N) y( m; _' s  X( N
  142.         public bool IsReusable
    ' A5 P) E) G+ ^5 s9 A6 E" d
  143.         {
    % R% g: G+ f3 ~# t" ^
  144.             get
    9 B0 ]: i# z  ~- o4 p+ b
  145.             {" ~$ }  n* H: i8 Z4 ^
  146.                 return false;: }4 W) U& b) J/ q
  147.             }
    - n9 O8 }* b& E' U$ p
  148.         }
    % G- L6 V+ S0 t& U9 ]- m
  149.     }
    . K/ ?' l( ^2 {+ i
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
; a( ^* _  i6 E: S% E5 ~. F" R
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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