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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
/ V9 ?9 i! d( t; b& f
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    3 @5 v' J7 y' @, u3 I; z
  2. using System.Collections.Generic;* S7 m+ o: x: |& @
  3. using System.Linq;, z" z: |4 q' C
  4. using System.Net.WebSockets;4 I# {# N9 H$ ^3 i
  5. using System.Text;
    , T& k6 L6 T  g+ z) X  W9 @0 M
  6. using System.Threading;- D! a3 U) X8 \: o2 q6 R
  7. using System.Threading.Tasks;2 y8 i9 n$ @+ J, U% ^
  8. using System.Web;
    4 ]+ s; }' k! D& d+ N0 R
  9. using System.Web.WebSockets;
    & K  ?' X) y0 N2 v  B, Z7 X& {

  10.   ~# r( E7 V1 y4 p9 a+ }
  11. 6 _$ Z5 u  _) W6 j( ]2 k
  12. namespace WebApplicationWebsocketHandler4 m$ l1 G: O# {% T
  13. {2 B" C% R5 f1 Y4 j( l  E, _: p
  14.     /// <summary>) X1 s5 S4 Z# t. m7 ^
  15.     /// 离线消息+ @* S7 _7 H! o
  16.     /// </summary>) d6 K" H, j* t) \2 Y: r( I
  17.     public class MessageInfo% v  [% C# u, Z
  18.     {
    7 u: {6 c) e1 m' D+ Z' x( q
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    . t( u% ^# k3 E% d9 q8 ]$ K
  20.         {5 p! @% P% E, t  s
  21.             MsgTime = _MsgTime;  X& @8 s1 P: _: ^, V
  22.             MsgContent = _MsgContent;) h5 f; }1 k, ?4 A3 k* M' v
  23.         }
    1 w5 y$ n$ t0 i2 K/ u8 Z! u
  24.         public DateTime MsgTime { get; set; }
    . Z5 c  g, R- l6 K" u. Z( Y
  25.         public ArraySegment<byte> MsgContent { get; set; }1 B4 r" e7 T' G+ `4 J
  26.     }" r4 {8 X0 A! C- l( O. J

  27. * ^0 ~2 y+ Q  B, ]5 ^

  28. + [0 j1 N2 g, w; s! x
  29. $ l5 O% d  k% {" l6 O. b

  30. - j) u5 d) \4 g
  31.     /// <summary>2 p5 v& G) N& t2 x
  32.     /// Handler1 的摘要说明. V8 B/ C! p& f  U2 T
  33.     /// </summary>
    ' N/ \) V5 m" }$ o1 v$ j$ T' {5 h
  34.     public class Handler1 : IHttpHandler
    % D9 j% P$ f4 @9 E. C; `
  35.     {# S: S9 ^) Q! m. l
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池1 B+ j0 U% d! g8 m/ d  x  Y
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池: u' f+ l1 F1 e$ k
  38.         public void ProcessRequest(HttpContext context); G8 N1 U+ y% `3 ^: v; p" ?
  39.         {
    * a, g! o7 l2 F2 o7 H( W( ?
  40.             //context.Response.ContentType = "text/plain";6 W0 y8 V; b7 V2 g' |6 z& V7 J' m
  41.             //context.Response.Write("Hello World");
    2 l1 U( {6 \0 N, ~* e
  42.             if (context.IsWebSocketRequest)! n4 ^. h' h) [9 {
  43.             {0 _: k3 v$ d3 l- t1 r$ }
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    $ n+ i4 a' l. F# p, I2 o( Q6 ]. ~
  45.             }
    & H+ n1 a8 P3 ^: i3 _+ g6 ~
  46.         }: w; w# U, t9 A5 x

  47. ) b6 @/ x5 Z2 g6 n; ]
  48.         private async Task ProcessChat(AspNetWebSocketContext context)) [  B% m6 {9 i. T4 L: h
  49.         {
    ' p, s( l2 d$ k
  50.             WebSocket socket = context.WebSocket;: k1 o& F" a( w; X, L: y  N# f
  51.             string user = context.QueryString["user"].ToString();
    7 i* ]4 y- d' d

  52. 4 Y8 j/ j7 X  q# @* m0 t; X
  53.             try
    0 Z4 J0 a' H5 a  z
  54.             {. [! U( V  x' W0 S# p& c' R
  55.                 #region 用户添加连接池1 E5 ]6 D+ h! \8 ?" B# F
  56.                 //第一次open时,添加到连接池中
    2 ?1 l" E1 B: @) c( Z
  57.                 if (!CONNECT_POOL.ContainsKey(user)): G+ w- L4 Q! [
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加% K6 ~: e) u5 x) j
  59.                 else: g+ h) d* c. ~# F  l5 U
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新8 _$ L4 {$ I/ i9 Y5 h+ i; ~
  61.                         CONNECT_POOL[user] = socket;
    ( `) {/ F: `9 N$ \+ h5 J
  62.                 #endregion' e" I7 C% X7 O+ @+ V" q
  63. 5 G! `* W6 U! E. R$ I/ _0 A0 u
  64.                 #region 离线消息处理
    ! D8 |8 @, t' \0 C: x' Q7 O
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    ; V2 K8 b1 X/ q* Q/ L
  66.                 {
    0 G, G' U; e: }9 I
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    # ~- q4 G7 _2 R) @/ F
  68.                     foreach (MessageInfo item in msgs)$ _" [% c0 x6 C! v" X% y  n# T
  69.                     {- ]9 t! W1 z0 `: R+ a8 e
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);$ {# h% E+ S" x7 q' _$ q; Y
  71.                     }* V3 g$ I" V# J1 f6 r
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    ) r6 w3 Q4 t! t$ i. N
  73.                 }6 ^1 ^9 `+ E8 w& G1 h) D5 S
  74.                 #endregion
      \% ^4 f8 O* f! Y( J+ [
  75. / M, b: O2 y$ n
  76.                 string descUser = string.Empty;//目的用户  C& E) T( i. k$ Z! K# z. C- e
  77.                 while (true)
    # j% j4 R+ n' v+ A2 ]6 h1 J
  78.                 {
    $ ]# e9 c' S% n  L; j
  79.                     if (socket.State == WebSocketState.Open)' L" ?/ P/ B: w9 `
  80.                     {4 z% D7 }( N5 w" s
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    $ P% S* I* Q5 ?9 D$ I
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    + X" @0 Z+ l9 t; f: u
  83.   r8 ~( J: L" X, E% s
  84.                         #region 消息处理(字符截取、消息转发)
    " m6 i6 N" {. k: A8 ~) G4 g
  85.                         try2 o! ~& a2 c0 t% ?4 n9 |
  86.                         {" D. A/ V! j' F! G7 Y
  87.                             #region 关闭Socket处理,删除连接池% Y, g9 w/ M/ `/ @
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    2 f3 g2 f9 W+ X  O# u1 H
  89.                             {: N$ t/ d7 {% [0 A5 z- |* ?. R
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池2 _# t* V0 d4 x" {$ f3 O1 J! a7 {0 w
  91.                                 break;
    8 g9 S: ~- n0 F) k1 S
  92.                             }
    , B, M. @% D9 y4 i# A2 F( E, ^! h
  93.                             #endregion4 L4 n! M. }' S+ u
  94. 2 u2 X* {8 T2 e. u' I
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    & ]) o! T6 A9 w( ~3 `
  96.                             string[] msgList = userMsg.Split('|');
    - P- ~' G% T' z% J5 d
  97.                             if (msgList.Length == 2)
    & i; L' Y* v. f" ~  u# g. v/ z
  98.                             {4 D6 h' T$ x/ s4 J/ ?/ J
  99.                                 if (msgList[0].Trim().Length > 0)& {6 I' x: g/ o4 L( ~
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户, `* n7 M" e# Y
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));; x" T$ m' a3 M; N7 d( e. U3 F4 l
  102.                             }
    ) O3 M! \9 A) F! o5 g% H
  103.                             else: T; X4 e3 F; v5 g
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    ! Q+ u7 m' K9 y! B' r

  105. # p* }8 O3 r3 _* G
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线1 n, d' W  M" m* B
  107.                             {
    3 k) u* c% O/ {' o: \# k
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端8 a5 \2 Q5 h8 V7 x9 y) P
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    - w5 [" b4 V6 ?
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    9 u* [% _, X; T' S# g5 z3 f7 K; E
  111.                             }- v' g/ B9 g6 j1 C- L- d! w
  112.                             else
    8 ~! R1 m) _) @8 h2 x
  113.                             {
      q; W' T, J- R4 ]4 u4 t+ a
  114.                                 Task.Run(() =>0 e" d0 ~8 ~5 [' u( o' d
  115.                                 {
    + @9 F$ z3 e- L8 h8 ^4 d( m
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中; q/ o+ r3 p& g8 i% X& A, e8 N
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());( z+ F: k6 K9 |
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息; V) H: `% }' q6 g% A5 d* p& l
  119.                                 });
    7 M  l' \, j/ c0 Y- _' w: {# `
  120.                             }2 z* |- _/ Q& C# B  Q9 [# G& N5 @
  121.                         }
    : B  i$ i* I/ `* B0 h/ T
  122.                         catch (Exception exs)
      v# r$ d% F; ]* t+ m& P4 z, P
  123.                         {
    ; T2 R( _' s( B6 S9 A3 C
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息$ p7 k6 ?) S3 d6 I+ d2 q" M" w
  125.                         }; P! E0 }( h( O, B, o1 G
  126.                         #endregion- K, g1 D% \0 W' G# O: `. V$ S6 t
  127.                     }  _  G! e" S8 v) M, R9 f+ Q4 u
  128.                     else
    % {8 S: _4 k1 n9 y' Y$ W- W
  129.                     {
    ) ]$ k% H6 m0 [7 m' p
  130.                         break;
    8 S+ g7 w1 H' }) E
  131.                     }- x: }4 t7 W0 J$ V- ^- F
  132.                 }//while end
    ! J5 t" S& ~. v+ b6 L8 [
  133.             }0 U5 ?4 S" {1 x, q( }& w5 `
  134.             catch (Exception ex)
    9 o7 ?; d: ]6 r# m( K+ d7 J- |  E
  135.             {
    ( x5 ~  V8 ~$ X: l
  136.                 //整体异常处理
    4 t% _. d' D/ T& C: w
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
      b/ Z0 Y' @+ P: y
  138.             }
    4 E; P' ^% F' G# C9 e: H
  139.         }
    2 @0 z' D% \3 H/ j
  140. 7 D: N9 D7 r% \" f8 E4 A( c8 Q- h3 m
  141. - n4 Z7 N2 ?' O9 S3 ~/ O3 v
  142.         public bool IsReusable0 w2 X! q: i0 h2 Z
  143.         {
    ; R( o5 x2 s0 d- B9 n% \& [
  144.             get
    1 j, ?" F. R3 u1 W9 h
  145.             {* W0 {6 {, ^  ?  a. k
  146.                 return false;
    3 D8 E, m- M* ~0 s( e6 d+ {, l$ z" t
  147.             }1 {4 i5 m& l1 p: q: S1 I
  148.         }
    ( F0 p# o8 [0 g1 s: j
  149.     }6 I% `! X, S! \. C( o/ H; H7 h+ c
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

2 S( b9 d5 [4 ?* V
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-1-30 11:36 , Processed in 0.058720 second(s), 22 queries .

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