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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
9 `- q. F. Q. b  k/ U" Q
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;: O- [' B- G0 r- C2 P
  2. using System.Collections.Generic;
    2 y% P( W/ u, A& v. B
  3. using System.Linq;
    8 L) _; G1 L8 k% s* `; S2 G5 u
  4. using System.Net.WebSockets;
    ( B# H, M8 ?: u: g8 I; u6 q
  5. using System.Text;6 M! S$ c8 U* P: ]  n
  6. using System.Threading;
    " q% z" N. i( d9 I0 K# }, D
  7. using System.Threading.Tasks;4 u) l" t9 J0 W/ y+ ~" \
  8. using System.Web;
    , w7 ?# e& g& t  v
  9. using System.Web.WebSockets;
    + u4 K, e) X! ~3 U
  10. " }6 d7 W# q/ @* ^
  11. ; N+ F, S6 F/ [6 S! S; R
  12. namespace WebApplicationWebsocketHandler: T% z) l9 x' t  F
  13. {9 n! |3 ^7 z$ T, t0 x; O
  14.     /// <summary>
    % i1 _/ Z: G1 A# D' ~3 d2 z
  15.     /// 离线消息
    # A+ m7 P  E! ~/ s- S
  16.     /// </summary>
    6 Q" O( ~! ?! W/ n
  17.     public class MessageInfo
    ' s0 p: k; f( S
  18.     {3 [5 n& s7 W+ n- k9 o, P7 w
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    # p) I- Z$ R" Y; ]
  20.         {
    9 c3 `8 Z5 S( z: r
  21.             MsgTime = _MsgTime;
    9 ~! D, b: I. k: l2 p
  22.             MsgContent = _MsgContent;
    " h3 t* a" }5 [3 l/ i. G$ s
  23.         }
    5 e) R. W9 r2 A5 D& d* G
  24.         public DateTime MsgTime { get; set; }- l& @, X5 J2 {: [) R/ C( _
  25.         public ArraySegment<byte> MsgContent { get; set; }
    5 ?7 V& X" _0 Y- E; u4 G; D
  26.     }
    $ r% x7 n' [$ o  }6 e# @

  27. 9 [/ {) d2 d* t5 Z, G
  28. 1 F- ]  P8 z5 K

  29. / q0 m( E9 {2 {7 y% m

  30. # Z6 _7 k3 c2 v; k6 T9 Y9 E
  31.     /// <summary>+ S  J! w3 v3 Y( r7 |, ~
  32.     /// Handler1 的摘要说明' t, D6 h. p3 z* V
  33.     /// </summary>8 W8 u, `, u9 {  R/ w4 Z+ t* o
  34.     public class Handler1 : IHttpHandler
    ( S( l+ n/ i* q  |% F; B( `
  35.     {
      |8 I6 y2 ^6 ^" z1 D& B. _
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池+ X0 ?7 e+ X/ ?% r, D9 e8 J% ^  i
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    ( p4 q' }( K: K9 `" C  Q
  38.         public void ProcessRequest(HttpContext context)
    7 J/ ^# a" l) F; ^4 r' C: y" R
  39.         {
    0 Z, n8 g1 c- v5 l* s7 X" J* }
  40.             //context.Response.ContentType = "text/plain";- Z6 L7 `4 }( N
  41.             //context.Response.Write("Hello World");
    ' K. k2 x3 |2 F' f( O$ F1 x4 Y
  42.             if (context.IsWebSocketRequest)/ @% c. G5 T; G- a  N, `
  43.             {9 w+ Y2 `2 D. r9 |2 U
  44.                 context.AcceptWebSocketRequest(ProcessChat);7 ~  E# T/ \  K  M$ [6 O$ u0 R
  45.             }
    ( Z: P7 Q: K. w, \2 r5 c; j
  46.         }
    / M2 I: q6 p0 q; t

  47. 3 J6 h5 b7 ^3 E+ K
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    % G$ a0 f5 C$ o$ r8 O. g8 I! a3 b6 M
  49.         {) D8 `7 W+ N3 m4 V/ i4 P' b
  50.             WebSocket socket = context.WebSocket;
    0 P' _1 @3 ]7 Q1 E5 I. a2 V5 Y; s
  51.             string user = context.QueryString["user"].ToString();
    2 F$ E' h" @3 E2 S8 k: J! _9 M; n
  52. 6 I& x. _& e% ]2 j( x0 m
  53.             try# z9 m5 W8 A  o9 s8 p
  54.             {
    " S* Q- x% f; b  M) V
  55.                 #region 用户添加连接池
    3 f. @. g& g) m2 x5 {4 e
  56.                 //第一次open时,添加到连接池中
    4 x; G9 F( E0 b8 X" D1 u/ w( [
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    ; S5 r8 h' D( H2 ]' I
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加% V5 i, E. X, A. e. e" f. l$ N( H
  59.                 else  n9 Y$ D3 `; ?" B9 C! x) v
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新  p5 ~+ m" g0 T1 h* y; K$ f
  61.                         CONNECT_POOL[user] = socket;5 d& [- D- }3 ]- h3 s+ `, b/ _9 o
  62.                 #endregion( l3 ]2 u- n6 n
  63. / s2 K9 G! z: s: M$ a, P9 G
  64.                 #region 离线消息处理
    0 o7 l' k# a2 l7 f1 B* N
  65.                 if (MESSAGE_POOL.ContainsKey(user))1 L3 G( Z; c# B/ U0 o& l7 c
  66.                 {
    ' N: N0 n9 K# @. a0 `9 g/ E' T
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];# B: Q* s4 k8 z
  68.                     foreach (MessageInfo item in msgs)% Y$ ]. h+ D" ~" E9 g
  69.                     {- p; q& y* c, d; P4 i+ y& i
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);8 u7 E  ~9 O! s7 Q8 \( }
  71.                     }% }0 j5 \# ~3 _3 k/ H3 W
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息3 I; q2 h/ f! I+ x$ s
  73.                 }' j6 w2 }, E( t5 R. i- u( O
  74.                 #endregion( E( i: U: E% o0 ?% b6 Q5 X

  75. 5 b# j& }5 n: P  J1 x0 e
  76.                 string descUser = string.Empty;//目的用户% n+ K% R1 X; W& J3 \* ^6 a
  77.                 while (true)
    . N- y7 L3 K3 c* {& s: _
  78.                 {' |, [( p- [% W
  79.                     if (socket.State == WebSocketState.Open)
    ( O+ x! B( ]) |8 Z3 f% z
  80.                     {6 w4 o7 ^& m" f
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);# I& l6 e# _2 G% [* G; o
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);6 r& y& r0 x6 J2 }
  83. * I2 P0 `+ W' g9 R+ h
  84.                         #region 消息处理(字符截取、消息转发)* q- Q2 H% \' @/ P1 G8 W
  85.                         try
    , Y3 _. Z6 t! h; @# D
  86.                         {0 o* I; D6 x, N  u9 q
  87.                             #region 关闭Socket处理,删除连接池
    + q) Q: W! C: E! H4 f- |- K
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
      m" Q) {; f2 h) X* ^% ]* i. \
  89.                             {
    # T) U$ C7 D7 W  a: P
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池3 r: H0 b$ x+ X+ L* Q1 ~
  91.                                 break;
    2 j- \7 K  V& B7 u  h
  92.                             }( ?$ s! b3 r/ q
  93.                             #endregion
    # [8 P+ g" x8 T4 X' v' _4 c3 i1 K
  94. / \! B( U6 J3 j6 Y9 d
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息+ Q* W! T7 Q) A
  96.                             string[] msgList = userMsg.Split('|');
    ( V: x$ d  r6 G
  97.                             if (msgList.Length == 2)
    . f+ k2 j$ n0 {1 o8 q
  98.                             {
    - o, E/ _% j  r  X1 x; `
  99.                                 if (msgList[0].Trim().Length > 0)
    " N9 p9 a' z& G0 Q7 i7 k0 p
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户+ O) P8 i1 ^$ J. J' @( [; F) S
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    0 m( Y3 q  ]  G8 I( U
  102.                             }9 x2 Z: W- |: r% n# F  ~
  103.                             else
    * O3 @' f3 g" ^1 w! A
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));! [: J0 }( s4 Y( d; B+ t

  105. & h. V9 U  F& S" g7 s
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    % g6 N  F7 A; Q, ?' i4 D
  107.                             {
    % @' v5 `& M( I# b5 I1 Q6 L
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端0 J8 z5 {: ?* Z+ E
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)9 q( u+ P) E' m4 ?% n% V1 `
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);+ t& W* h8 y$ B
  111.                             }1 y% Q! o' _* v2 z
  112.                             else
    " J& B- o8 D, @  `3 i' n
  113.                             {3 |# C; K, q' s; t
  114.                                 Task.Run(() =>
    9 I' |% ?  i* i' u9 w. d8 Z
  115.                                 {0 L, D$ A  e( v9 u8 Y# H
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    2 t' \/ N; o0 W. w7 W1 k
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    ) L/ \2 j( \0 ]2 l4 P' O: r8 N
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息- ]/ x7 {+ T' l
  119.                                 });& H  h4 \: D3 w& q0 {
  120.                             }
    7 V) g: q: z4 ^; I+ `
  121.                         }
    1 k! A1 ]: r9 E: j9 d* F
  122.                         catch (Exception exs)
    9 n/ {9 c0 W8 ?
  123.                         {+ }. {9 h% H. o( k2 ]' K4 W
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息$ {; C- G4 O. h4 K" B
  125.                         }' g7 J: ~$ ^" `# d9 W6 @
  126.                         #endregion6 X! K, W7 ?, ~" M
  127.                     }
    ; @$ ]' ~6 h9 ~% p" ^
  128.                     else
    ' O# r; M# h+ |8 C4 s6 y
  129.                     {
    ; O) d% }! s" w( b% G7 q
  130.                         break;$ W& h! p/ O" {6 N
  131.                     }
    3 D6 d5 g( X) p% K5 W
  132.                 }//while end: y4 W$ o! x+ O
  133.             }
    3 F% s! J0 j$ C/ K1 Q+ r; V) V: T! l
  134.             catch (Exception ex)6 k$ k: z0 a; w. k
  135.             {
    6 ?* p, k; H4 K
  136.                 //整体异常处理
    " H% p8 _" o9 I/ j
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);5 k( A" P; t7 D  V, a$ S, m; h
  138.             }
    4 v5 ]& `3 b+ j" x
  139.         }
    " ?/ ], H/ t7 ?
  140. 0 K2 g  D# b/ D7 \

  141. : s6 l' D* S* z0 P7 ^& a& }2 w% A
  142.         public bool IsReusable, J: P; [3 e4 t& }4 _
  143.         {) d7 A2 A) F+ V) C3 Z) \
  144.             get
    5 Q( Z3 B1 n$ p; G" |1 l  f3 _$ G
  145.             {& {* {2 w# ]4 Y- Z1 W  h
  146.                 return false;
    $ R- E1 q6 b" F9 T" H0 R+ H1 a
  147.             }" O/ x# N! @7 Y  ]3 s" C
  148.         }9 a1 }  e& v/ I4 H+ k2 o: A* h5 t
  149.     }
    & C3 Z. o5 V; `7 B; W* i
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
2 Z) U; U% E) s( {) Y- i
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-18 23:08 , Processed in 0.124527 second(s), 22 queries .

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