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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

& d; }0 c) }, e1 h! t) B' p; I  M
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;4 i3 ]0 V% @* I5 v  l
  2. using System.Collections.Generic;
    * V% G4 x9 g: _0 \. C9 q, Y" j/ R
  3. using System.Linq;; u+ e( q+ l* t1 x6 s/ }
  4. using System.Net.WebSockets;4 n; d, W6 _6 E0 ^
  5. using System.Text;
      G' P; O5 t9 Q# _0 }
  6. using System.Threading;- W$ ^5 u& B1 @- V9 R9 `% D/ d
  7. using System.Threading.Tasks;
    # L, t% L( D/ a- v, ]5 A0 ^5 U
  8. using System.Web;
    * \7 }6 ^1 P% A* n) M' u( Q7 M' \+ h
  9. using System.Web.WebSockets;! v0 p* ^# H; t+ x4 T3 `
  10. . F5 u$ z. D  Y2 g$ n$ p% D
  11. 3 P' J" u/ h+ n" E4 z7 h
  12. namespace WebApplicationWebsocketHandler
    3 U6 D; U* n  y, ]4 f
  13. {) |9 D, V$ o5 [# b
  14.     /// <summary>
    ' T' b% a% z# Q' O0 u. J
  15.     /// 离线消息
    / k; P; w# G, W  i
  16.     /// </summary>, T# ~! O  K5 @$ z
  17.     public class MessageInfo4 W# k- t6 I6 L. W. C) T7 P2 L
  18.     {
    5 e9 m$ E1 u/ H# L. R! r. r9 I' @
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    : X" W8 I, J9 H/ E$ V9 D5 _6 e
  20.         {
    % u5 r* g, ^" K3 t# M
  21.             MsgTime = _MsgTime;+ F+ }+ [+ {; n
  22.             MsgContent = _MsgContent;* W! ~' A( V0 X6 i2 \
  23.         }
    1 e- }7 F" j) ^. `; P. s( E" ~
  24.         public DateTime MsgTime { get; set; }3 U1 ^  K/ j- L2 }1 K+ E+ d
  25.         public ArraySegment<byte> MsgContent { get; set; }) ?% |+ l! q. N6 X& z
  26.     }9 T- S  S$ J* @

  27. ; S/ F% b7 s0 ^

  28. . u/ L: h8 _1 N2 a- W% c
  29. . p$ v. h5 [2 e3 O; @! V  @
  30. % C, I$ |' q% S$ L) C- D2 z
  31.     /// <summary>
    " j; h6 W/ F% a& N
  32.     /// Handler1 的摘要说明5 V& D& b+ S' p* o. S6 {
  33.     /// </summary>. ]. {" }% Z  F1 }
  34.     public class Handler1 : IHttpHandler5 N1 @4 {' g8 j$ O# l
  35.     {
      U. [6 g3 p1 C
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    $ s/ f4 ~$ V* A- g' p7 l8 y  h
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池9 A( H2 K4 B2 q3 C: x& y
  38.         public void ProcessRequest(HttpContext context)  F% ]% b1 J3 N& T: n1 D! P7 u
  39.         {/ ^' G  F/ H) ]& t5 {; k
  40.             //context.Response.ContentType = "text/plain";/ P# A% ^8 p! d% K, g3 w) \
  41.             //context.Response.Write("Hello World");* X6 S: ?6 R# Z/ T( J5 z
  42.             if (context.IsWebSocketRequest)* V: |) }6 a6 n' \: z4 G
  43.             {
    ( R+ z6 V  g7 D2 y9 L  \; v0 B
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    ) n; c2 S9 @. ]# f* n
  45.             } ! q! p, o9 o* u
  46.         }/ L1 V7 j8 B% x
  47. " h4 b/ r- I; ^( p! ?0 J
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    * p0 [; B) w5 b4 k$ y
  49.         {0 n! G8 T9 V6 J) y( X
  50.             WebSocket socket = context.WebSocket;
    $ p" g$ s2 x6 `  \
  51.             string user = context.QueryString["user"].ToString();9 W' y! y: B: k) \$ x
  52. 7 Z: a  L+ p" N5 T$ _4 }
  53.             try8 R1 S) w! {2 y; M% f6 T
  54.             {% G; [' B4 ]8 i: u1 p2 e
  55.                 #region 用户添加连接池/ S& ?7 s0 @2 T1 m$ T
  56.                 //第一次open时,添加到连接池中! S$ W9 H3 {6 W  [7 d0 v0 H9 c8 L
  57.                 if (!CONNECT_POOL.ContainsKey(user))/ P* d8 _" L9 b& `
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    ; N2 v- P" ]* H# ^
  59.                 else
    6 G# I2 u, E: |: U% z' F
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    . e. h2 s2 U$ w
  61.                         CONNECT_POOL[user] = socket;6 f+ m8 }' O2 K- q% ~
  62.                 #endregion
    : W) W" F* j  v8 s
  63. 9 r0 D2 R5 H5 G- N
  64.                 #region 离线消息处理) Y  t( V% ]( M
  65.                 if (MESSAGE_POOL.ContainsKey(user))$ \2 e* r, R7 @( {: X. @) l/ D
  66.                 {
    ( r* J# @  o) W! X7 m% `7 a
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];+ Q# O+ {, ?1 u/ e( i$ z
  68.                     foreach (MessageInfo item in msgs); @/ R8 [* O* p5 m. a" `
  69.                     {. l6 f4 }4 d: q$ i* A3 `
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    1 B5 J6 t8 r) @: k) w" c
  71.                     }
    6 l4 ]& }. `9 D" K. e* o
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    + G& K' m" g5 W+ @4 S
  73.                 }  L+ F8 h) Z7 E! Y( f9 p. v
  74.                 #endregion! |2 O- y4 E; g) {, t% V

  75. + b' ]+ V8 z# A! j0 r
  76.                 string descUser = string.Empty;//目的用户, F# L! t8 ~$ h8 D0 D/ q: e+ Y) q% I. X) n
  77.                 while (true)
    $ q* x8 N* c# p7 ?- w* S
  78.                 {! o5 P" w: B1 K7 Q; O0 s/ B
  79.                     if (socket.State == WebSocketState.Open)
    7 y0 }" K1 e2 [9 b
  80.                     {
    # z% @1 y, _  e5 @5 Y6 }
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    ; r6 ^9 j9 b' e( u( B3 v" V& @' U
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);$ H9 n8 c5 K: ]5 t* e! y3 S  [; Y

  83. + R* `8 T5 s1 L3 [0 C0 G) s9 i0 A1 ~
  84.                         #region 消息处理(字符截取、消息转发)
    ; C* y( k2 ^2 z
  85.                         try& o' p5 K. ~9 _: V$ t8 t& @
  86.                         {
    ( I+ I9 r1 I+ f+ n) l4 Q. l
  87.                             #region 关闭Socket处理,删除连接池' W$ E$ q2 N- @4 e
  88.                             if (socket.State != WebSocketState.Open)//连接关闭$ Q0 j/ h( g4 g; G
  89.                             {4 b8 b8 ]5 ]6 d3 D4 c
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池4 W; Y$ S2 w8 N
  91.                                 break;  Z1 x' V! f8 x$ g# D- u: e
  92.                             }$ w8 c; _. m- K0 K
  93.                             #endregion$ y* U$ Q4 _# t6 U4 _

  94. % B5 _9 I  H; C: r* S+ D$ o
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    ! w3 _6 o. s  d( ~7 ^* T
  96.                             string[] msgList = userMsg.Split('|');6 w- {+ P% m  J% i3 x# l. f# c
  97.                             if (msgList.Length == 2)
    ! K  E  u) y) p
  98.                             {  S. p8 H8 r8 {2 e1 H  Y2 B
  99.                                 if (msgList[0].Trim().Length > 0)
    ) F; q, z$ B! ~$ T
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    ) `( u2 M$ T& V  [
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));. \0 F2 \) J- u4 C' \
  102.                             }
    5 }- ?4 L- h' Y' g
  103.                             else3 F6 W% I# l7 r! T; c8 O; m
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));5 l, o" s5 ~/ [* s+ j/ O; \
  105. 1 {# j' W" q9 F: E
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    / k' B7 G- x: e" m! }
  107.                             {$ k+ q( E! v4 f) I1 }0 V/ U
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端. u" I' f+ A6 m5 o, f9 \% L
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)2 c& n2 P, V3 O8 U1 d. X
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);* n# n$ s$ W" }, k
  111.                             }9 z. A, M4 M4 ^) j  u
  112.                             else; I- R% N3 y8 m. w
  113.                             {( d# m2 m& G9 G' S& j) U  j0 v
  114.                                 Task.Run(() =>9 h8 Y8 W* A2 m/ O! }2 T9 O
  115.                                 {
    0 [/ `" x' c6 ?+ q8 r/ @; a
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    % R" S3 w- g9 q
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    5 c3 t7 Q3 R) @. {1 v
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息3 V1 G3 L! r: W0 s; q4 X/ `
  119.                                 });
    ; S8 y' P2 P& I8 W# D- @) r
  120.                             }
    8 L& F0 r: X7 t# I3 x7 ^. K5 C
  121.                         }" Z4 g5 y+ v) C3 a
  122.                         catch (Exception exs); p9 E' M" W5 K. k% t- R4 A' |4 o
  123.                         {. w! I. ^2 k* u" y# v
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    8 D* _- t. `$ s2 K# z8 q  h5 ]
  125.                         }% I* a/ m/ ~3 `/ D) l' Q) l9 x# X
  126.                         #endregion/ B8 I0 H5 [7 @0 x
  127.                     }$ y; A9 i8 O0 c, Q) ~; P6 _% }
  128.                     else6 b: O2 l1 z2 m; _" \8 ~  F
  129.                     {
    0 P& |% x' }' F+ z
  130.                         break;
    ( V( B/ P1 t7 w- ^
  131.                     }
    & J% b. X2 n7 h' f8 V
  132.                 }//while end/ Z3 U  m9 y7 y9 C
  133.             }
      b2 J6 \4 a* n! v; P
  134.             catch (Exception ex)2 O3 M' K2 t. U+ y% c/ P3 B
  135.             {
    9 @  A+ v3 |8 H; u0 s
  136.                 //整体异常处理- m! T- l4 }8 L1 H9 U
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
      _' X" g3 t( s: r
  138.             }
    - v  i3 V. ?1 L: J
  139.         }, Q6 p6 w0 d9 ^; O

  140. # M: W# o1 X2 ?+ S# n
  141. 2 x* S+ A) a* i" F, {- `
  142.         public bool IsReusable  }/ G# s* W& h0 a8 H( M/ W
  143.         {
    # Y1 ^. x, |) t0 Q7 m4 g$ l
  144.             get) w! n1 m* V+ g
  145.             {
    3 ?3 E' e$ W" O
  146.                 return false;
    ; G9 S( l/ j! n0 k% Y
  147.             }" M% D# a& X& ^  Z% E
  148.         }) f4 {# G. G9 K4 Y0 N
  149.     }
    ; ^$ z& K. u: {& V6 `1 k) k! B+ f
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
# U+ ^& V. h' D1 I, `
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-9-21 07:23 , Processed in 0.059554 second(s), 25 queries .

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