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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
8 k/ E  C  u1 @; F0 n: K/ ^
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;0 K/ D' b  i) E7 M
  2. using System.Collections.Generic;
    9 q* B" T' m1 ]7 P5 M1 W( K
  3. using System.Linq;
    ; {6 k5 h) s" w' V- u  D
  4. using System.Net.WebSockets;. x7 ^/ `9 B  J8 }6 p
  5. using System.Text;/ H9 m9 ~% h! {3 |( A9 L
  6. using System.Threading;
    3 @' t0 c/ S( _7 A6 f5 E1 T6 C; \
  7. using System.Threading.Tasks;
    ' M7 M; g1 i$ y" y6 e
  8. using System.Web;
    / W8 H8 o1 C2 g5 t6 S
  9. using System.Web.WebSockets;1 f3 M0 W) K! ]9 {, n  ^# Q
  10. 8 s) T* \) ]7 W9 f2 ~: J5 J- O# ~

  11. * `1 C- i) L3 c
  12. namespace WebApplicationWebsocketHandler% X, K- d- Y6 O* C; P
  13. {
    ; t/ a4 L9 g' y# i
  14.     /// <summary>) x2 x4 V9 a, N3 M9 H, o' m
  15.     /// 离线消息
    - L! G' @4 D* r# L
  16.     /// </summary>
    $ ~3 ^3 r. X. F# g8 \+ z
  17.     public class MessageInfo
    . i7 x2 a* ~. o4 k* a1 w6 O. Z5 t
  18.     {
    6 {/ ]! |0 g" N* N2 X6 g/ Y# ~1 C
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    8 W1 e( {, R& t3 U
  20.         {
    ! k! l; K( `" H
  21.             MsgTime = _MsgTime;
    & s3 q0 G4 B: L% a( k
  22.             MsgContent = _MsgContent;
    . O4 J3 m  M! D$ N5 [% Q
  23.         }$ @$ @+ d% F+ T' x& m" H$ O
  24.         public DateTime MsgTime { get; set; }7 _' m8 E$ W* V' E
  25.         public ArraySegment<byte> MsgContent { get; set; }
    # t6 m! \$ l7 W: S. T4 ?$ p$ ^
  26.     }
    $ m1 c9 T! ?/ g/ R

  27. % Y1 p4 s4 _; D- k+ f; b

  28. ; Y4 W/ w! a+ r5 R

  29. 2 b! A5 b5 m& r# l$ H: |
  30. 7 E( ^; m! j. k* V
  31.     /// <summary># @9 m8 r' Z2 C- y3 Q; p; [1 Q
  32.     /// Handler1 的摘要说明
    8 j  u$ [/ w/ v* y
  33.     /// </summary>
    : z' J( M5 ~6 d
  34.     public class Handler1 : IHttpHandler
    - J0 f7 U; J: ]3 `* C
  35.     {( o: n0 \, W! g8 d* G# M& F) V  r
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    + w2 |3 u/ E7 h- d
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池" n$ d: Q7 |+ `, V
  38.         public void ProcessRequest(HttpContext context)$ q  x1 C" I: ?% L. j
  39.         {
    , H3 u1 i4 T/ e! p0 ~  |
  40.             //context.Response.ContentType = "text/plain";
      i9 ]& ]; ]& f( E& R5 U
  41.             //context.Response.Write("Hello World");
    4 h$ l9 z9 ^( a6 Q7 r( n8 h
  42.             if (context.IsWebSocketRequest)  y' A& `8 Y4 r6 {$ Q0 y  f. d& W
  43.             {: h# S% a* M) `0 K/ {/ b
  44.                 context.AcceptWebSocketRequest(ProcessChat);$ _, W6 P* ]! B5 W
  45.             }
    1 L+ Q3 P+ v6 O. ]
  46.         }5 R4 p* ]& }5 u1 Y( j
  47. 3 h) l1 E/ }" V* m! S
  48.         private async Task ProcessChat(AspNetWebSocketContext context)& P& t( v" b4 g  }+ X8 Y: V& w
  49.         {
    1 n, B  E  H( T3 E/ r; I+ Z
  50.             WebSocket socket = context.WebSocket;
    4 i/ l% r, S4 |8 S; e
  51.             string user = context.QueryString["user"].ToString();
    3 V8 T# r  i; s! \2 @6 o$ V3 S
  52. 5 b- n& S; C. V6 h
  53.             try$ f% z% l. ]4 g
  54.             {% w% p( J5 s, O; r
  55.                 #region 用户添加连接池. c" l1 x- C* b
  56.                 //第一次open时,添加到连接池中
    1 p$ L. b, ?' h
  57.                 if (!CONNECT_POOL.ContainsKey(user))$ |0 j5 g3 p$ l: b, O8 i3 K; A
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加9 i# I# l8 Q: v9 S2 Q
  59.                 else
    6 h5 D6 I- z6 k7 g/ E
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新0 O$ T: I6 y% X) C- K
  61.                         CONNECT_POOL[user] = socket;
    8 U& N) A0 L% [
  62.                 #endregion; g. n* ?, E9 ]4 V
  63. + @+ s. ]" {) T: E! [. O
  64.                 #region 离线消息处理  l) T" d" D/ \0 A
  65.                 if (MESSAGE_POOL.ContainsKey(user))4 t# A; x) t& C: N3 }+ B% j$ l( w
  66.                 {
    3 g2 a3 [, j, E, L# H1 s: X8 Q5 x
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    4 u. T. Z8 ?5 {0 x% S
  68.                     foreach (MessageInfo item in msgs)/ F' l5 U0 P% B# C( y
  69.                     {$ H: Y# \! z: r% W8 k5 K
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    : C+ W  i$ c3 `0 n  F. \
  71.                     }
    8 D4 {& F+ G& P* e, z: s
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息3 p9 v$ h7 e+ e. \2 d
  73.                 }! q; O0 }8 |. g1 }" T6 d( K/ j6 ~
  74.                 #endregion& E2 v* {9 y- u; m8 h6 X
  75. , _: m% J& @0 T$ m& P* ?! U" W9 H
  76.                 string descUser = string.Empty;//目的用户9 K4 P' T0 q2 W7 B" L" `
  77.                 while (true)
    / S& K4 z: h* g/ n7 q/ T6 P* P0 L5 v
  78.                 {
    ! d  ]) o( u( l8 O( H2 D
  79.                     if (socket.State == WebSocketState.Open): J$ Z% S$ A. y: m
  80.                     {: W, F$ M( X; Y' ^/ Z/ A. F& J! l6 q
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);4 ~, _3 k! V! c9 T
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);& g+ z9 j# s& ?) |
  83. & G3 a7 E! j& V& g& |" h
  84.                         #region 消息处理(字符截取、消息转发)
    % @, N9 i* x- o' M# f
  85.                         try5 e- T- |2 p5 g& e: @
  86.                         {+ I/ G9 \! Y! T
  87.                             #region 关闭Socket处理,删除连接池
    & [2 w1 ^' G/ @8 g
  88.                             if (socket.State != WebSocketState.Open)//连接关闭0 `- j8 i7 J0 T
  89.                             {* ?0 M& }4 F2 _# ~
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    2 _9 U. _9 \) V% |  Y
  91.                                 break;( Y& B. J( ?3 S
  92.                             }
    - t$ A3 j2 y. E8 J3 |+ K* @
  93.                             #endregion
    2 A9 j% q; K1 g, V- M. K# {7 j6 O$ N
  94. + C6 f! g! J& h8 i  R2 {
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息+ y0 ?+ x0 M& p. j3 \
  96.                             string[] msgList = userMsg.Split('|');& e8 K9 R$ \) Q# k6 a
  97.                             if (msgList.Length == 2)/ e! a# `9 k7 |5 d
  98.                             {4 ^! O6 O9 B. X
  99.                                 if (msgList[0].Trim().Length > 0): s5 Q; {6 q6 |! ?& h
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    % Z& v* j! x! ~* w" {% `7 D( o
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    4 q9 P3 R* W1 v7 h
  102.                             }  m" k0 {+ J7 k4 R
  103.                             else2 i2 y6 n9 g; a  w& V
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    2 g0 v5 B; a6 R7 L; w5 o) ~

  105. % m, s# j5 Y% n# C9 M
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    0 J# J3 S0 g7 \8 q- O; v) M  B. ?
  107.                             {
    ! I5 f+ I- R4 D, ~- ~5 r5 ]
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端. ~6 N! |: G6 e5 }/ ?. n. O
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)+ V: z/ z, e4 r- D# k$ k9 Z
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    3 |. c# [! [$ e8 s
  111.                             }2 \( ?5 g# Z5 v" f: u/ p0 U
  112.                             else
    . k0 s! i- g) I# v
  113.                             {
    7 Z/ m) e# h& o; `8 G
  114.                                 Task.Run(() =>
    : G( G  U* q0 k5 F  [! O& T
  115.                                 {
    ! @* ]' D( ^! {$ I5 C  a. p  S
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    2 G0 w; s0 \4 Z( r1 I5 u) c: \! n( O
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());$ E$ }# N3 H3 g) ^6 k8 c1 ^" H- h
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息# r) F0 w( X4 _: @) h) x
  119.                                 });
    / {$ G8 I1 H, l! U& N. E9 B
  120.                             }9 M1 w/ a7 s8 E& ~: d
  121.                         }, q( d% F; ~! s0 |* \$ h# r  m
  122.                         catch (Exception exs)
    ( h0 s( L6 \% b0 W! }. a% y) c
  123.                         {: r& V7 Y/ ?8 ~. X( F7 S
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    5 `/ u+ T0 m/ }: ?, y
  125.                         }+ l+ U9 K; B# d5 _" E
  126.                         #endregion
    + {8 N3 b4 v9 }( o- Z* H. Z' h+ ^+ c
  127.                     }! g2 Y, N& Q  F$ `) \
  128.                     else
    . T6 I. \4 l2 C& y2 [* Z+ S" Q6 }5 [
  129.                     {
    8 ?3 h' B% L' {( N0 I6 z/ a
  130.                         break;
    7 I' }" E! e+ M, q5 g. w! t
  131.                     }
    7 J% R* x6 B! R
  132.                 }//while end
    0 r  t& V2 J- [% y3 ]' P- `7 Y
  133.             }. B( k6 ~5 K& {) x( O
  134.             catch (Exception ex)
    7 f) n/ S9 m* `( y' j. n
  135.             {& S( g4 S6 `+ d8 k) @4 y+ T$ e
  136.                 //整体异常处理
    + j3 d, {7 q" o) l% B
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);$ O' s+ x7 C# E% h4 K  r' n
  138.             }; R; G1 y! o+ Y9 N! G- x
  139.         }( Z+ y" |$ N; P+ _

  140. ; C8 F7 i% R# \/ e4 U& O
  141. ' ~+ ?, ~8 g9 Z" u$ l1 b
  142.         public bool IsReusable
    - [+ q/ R) r" f+ S4 x
  143.         {
    - c  a- B; T  F# `% G6 O& I
  144.             get
    + }! s1 }' U: z5 [3 d) D3 e
  145.             {
    8 S0 p' n' `6 K& w
  146.                 return false;
    6 v! P4 P! }9 r4 C4 Y# z' x8 A
  147.             }3 M  G( W: F' d% ^! H, {+ n
  148.         }
    ) I8 [) Z, |* b" J4 T% m5 b* ^
  149.     }0 Y5 p; [) k& P, q! S) c! F
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

! w- g! N! F* V$ Y& q' p
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-8-4 10:49 , Processed in 0.079036 second(s), 22 queries .

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