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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
) I1 v& H6 i+ Z6 J
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    ! e& ?0 Y. M8 e$ Z, l
  2. using System.Collections.Generic;% A) G/ U$ y4 c, y. J* ?
  3. using System.Linq;& V) r* g) s/ E$ l: T7 n$ e4 B
  4. using System.Net.WebSockets;- z: ^2 Y7 T& H% d+ x
  5. using System.Text;
    2 C3 l; Y& G9 A5 B0 x* v
  6. using System.Threading;, G/ M9 u; l+ C* K5 V" L5 z
  7. using System.Threading.Tasks;. j# W" h+ b1 I: |; V3 l. d
  8. using System.Web;0 k2 {" i; w% i- k
  9. using System.Web.WebSockets;
    1 g& f  s' ~* j4 ~# A9 x
  10. ) `% a3 r. @6 P" n. M; }

  11. ! p; p" q+ n& p; Y, Q4 ~
  12. namespace WebApplicationWebsocketHandler9 K1 ^7 r* _8 ], I5 r# [9 @
  13. {
    $ D, ~; J6 s6 x/ |- I* c) q4 N
  14.     /// <summary>( p- R  B' \+ P' G7 o
  15.     /// 离线消息9 n$ _& X% x5 a  J  ?; d
  16.     /// </summary>
    4 v! i& H/ m' f/ T) U' p
  17.     public class MessageInfo+ [) _3 S4 t$ Z8 H) L
  18.     {0 c# Y; H  G, S. V: T" C
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)- }$ v/ V0 \% r0 N/ C
  20.         {3 B8 m6 F* A& e5 V) A* G
  21.             MsgTime = _MsgTime;
    ) Z. S( o' h8 \0 L" F. H6 u- R- e
  22.             MsgContent = _MsgContent;
    2 V. o0 k* L, X( z5 g) d# Q  X
  23.         }
    % g$ C+ \6 S+ `# N4 T
  24.         public DateTime MsgTime { get; set; }
      B' |5 q$ H( Y$ M
  25.         public ArraySegment<byte> MsgContent { get; set; }
    4 Y. y7 Y* }8 x4 ?3 M! Q
  26.     }
    & I9 E1 H/ G9 ~8 r
  27. * ]- w+ C$ M% F+ m8 h' }

  28. ) Z* e$ I3 E& u& B( [
  29. 5 R+ z7 Y6 w# |( Y$ E7 }( A0 m
  30. ( A: j2 T8 r* T3 {6 {2 C
  31.     /// <summary>
    6 e: K2 h9 r6 ^
  32.     /// Handler1 的摘要说明
      x3 N/ r( L7 T. ]
  33.     /// </summary>
    * T+ y+ [" ?# L# Y" `
  34.     public class Handler1 : IHttpHandler5 X9 S: Z' L; [$ z; s8 |# N
  35.     {6 w$ E7 ^, m) `& C4 o. y% Q% t3 C, ^
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池* m4 e, Q9 F# r0 U
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池% c1 a* y( E  e  r% b
  38.         public void ProcessRequest(HttpContext context)
    9 Z2 [8 `0 \1 C! K: I
  39.         {
    ; v" f& `( y* T. R% p$ T" D
  40.             //context.Response.ContentType = "text/plain";, s; P! J; m" _5 r4 F
  41.             //context.Response.Write("Hello World");
    : i; D$ f5 L) [2 s
  42.             if (context.IsWebSocketRequest)+ H0 |# B" M- N* g
  43.             {0 r; \% L( t6 t  g& ]/ d4 [9 m
  44.                 context.AcceptWebSocketRequest(ProcessChat);: O- ?& s* N. \2 P4 I0 M
  45.             } 5 H+ Z. p! Q1 Y5 E+ s
  46.         }+ [) U  H$ q/ ~; ~" F; H) ?' ?
  47. " y6 V3 v- h0 N
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    ; Z7 Y  c9 \! c- B3 [& _8 T
  49.         {
    / B5 I& Q* ~# l/ \, d# \
  50.             WebSocket socket = context.WebSocket;
    0 {! p8 R6 [$ d: o; Y% O
  51.             string user = context.QueryString["user"].ToString();& N9 d9 O5 D  |" f

  52. / ~6 D& B) z- F. f; P
  53.             try; N( \' @  n& X3 \9 g' t
  54.             {
    & r9 D9 ^- n5 P+ U, t+ b7 L
  55.                 #region 用户添加连接池
    8 N* G2 k2 n+ F0 e* |* Q
  56.                 //第一次open时,添加到连接池中
    5 N2 ?- s& {8 x6 {- I
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    $ t0 a: Z) D" }) v* l. P: F
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    3 x6 S" p  T, _1 Y! D
  59.                 else
    : H- \% H' U/ z6 e& `3 Y& A
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    9 M" C& T+ C9 h/ @$ M. V
  61.                         CONNECT_POOL[user] = socket;
    9 D! e. K+ B( ?/ o9 g4 M
  62.                 #endregion
    4 ~% R& O7 K) ?
  63. ! |/ F) b1 B, u! P9 u
  64.                 #region 离线消息处理
    ) l; n& F# N5 `: H
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    % g: u3 T9 c9 r& b' e  M8 L0 z. ~
  66.                 {
    7 h8 ?2 \& k, `* K
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];0 x0 Q/ W" I* v: F/ q5 N
  68.                     foreach (MessageInfo item in msgs)% G. u; ~$ Q0 q( J! F* |
  69.                     {
    ) G2 l" O& R! Q( }+ ]5 q
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);1 ~% r: Y2 X* [
  71.                     }
    # m4 i" y7 Y8 E+ {  B1 B- j) C
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息$ }8 ?: E5 i) C4 q3 x: c
  73.                 }
    / Z6 Q6 ?. G9 O( p! e' B& Q. M
  74.                 #endregion. ^  H' q! W1 A! E- u

  75. , H7 S- |2 r* U1 Q$ L
  76.                 string descUser = string.Empty;//目的用户
    % g( U3 j7 E0 ]- o" L- T
  77.                 while (true)
    7 s) ]+ z& @; u- U/ b
  78.                 {! S1 g; L: V! O. X" n4 l6 ?
  79.                     if (socket.State == WebSocketState.Open)
    2 b4 y! k7 D% J# P
  80.                     {5 M6 w' [) v) F, R+ A
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);% b. U" z$ p7 E8 D6 f9 ^+ Y
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);: k. Q. T1 a4 D  L# r6 v* t
  83. % f/ r- B, f2 O
  84.                         #region 消息处理(字符截取、消息转发)
    - f0 F! ^  S+ M
  85.                         try
    2 ~; ]% Z0 `" }2 s
  86.                         {$ B- V7 @) q0 _% _6 ?% U% Z
  87.                             #region 关闭Socket处理,删除连接池
    - l+ x& c! K* h0 S) w! r- R
  88.                             if (socket.State != WebSocketState.Open)//连接关闭3 f: F! U# I) n) q5 o8 r7 H' `$ b
  89.                             {# n! y7 `* t8 n+ ^: E8 x' F/ |
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    6 M4 m+ ?. m; F! K) T- ?
  91.                                 break;
    5 Q) a% G4 V. b* d0 ]" j
  92.                             }: |/ W4 h  n9 E# [' a7 i0 V. f. z& |7 p
  93.                             #endregion  O2 s9 r+ b, c5 s$ `" o2 i

  94. + q! Z  W+ K/ V9 B8 M7 U, S8 x" d2 O
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    * E( m' S# b! I1 K0 n
  96.                             string[] msgList = userMsg.Split('|');5 N3 l) f- y5 {1 R
  97.                             if (msgList.Length == 2)
    ; W: }% S) Q% E
  98.                             {' m; F3 H4 i" q1 s+ k
  99.                                 if (msgList[0].Trim().Length > 0)
    $ N: M/ n6 _! H8 B- T+ m7 \
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户& t# n4 z5 k3 }) O. [1 L
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    + b2 R4 Z- P+ l( }& z4 W
  102.                             }
    6 h. k; n6 w6 O$ y
  103.                             else% ]% c% j% l8 f( e$ s0 e
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    , H+ a; v+ U4 ^- [) A

  105. / n8 ?6 Y# C- b
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线  F, \/ P* t, ~4 c1 R  L
  107.                             {
    / C: z) P' M7 x% G' l: @- p/ Z
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    , Q3 c) I6 S( c; I$ E, W8 K
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    ; U) c) \9 p4 l' f/ ~& E
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);! z/ w2 Z! t: i2 e2 j
  111.                             }2 u2 h% r  A% |) C
  112.                             else2 G" Y0 t- @7 U5 o. P9 f/ ^
  113.                             {* ]3 W) O2 |( d1 B. h
  114.                                 Task.Run(() =>
    / v: M2 x5 M! ?
  115.                                 {
    : J% i' C; H* Z2 }8 ~0 G
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中* w5 ?! a2 _2 X5 r
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());; x  y- R) t4 n4 ^: }7 ]
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息2 f8 b' @8 a6 l- @
  119.                                 });
    ; m% c' J$ o' Z) c
  120.                             }! C! [" s8 W: P. c
  121.                         }9 a/ _% r$ Y" D; ?  I1 O9 X' h
  122.                         catch (Exception exs)
    $ q+ w' `* [- M- s
  123.                         {# V$ H1 ?& r0 E7 c8 n
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    4 ^0 y; I8 V! y+ d( M3 y8 N
  125.                         }
    # S2 E  p( L( |1 Q
  126.                         #endregion
    " k7 G2 @( Z* b6 C7 H7 v# |
  127.                     }# B1 N& w! G7 p7 L
  128.                     else
    0 W* V' I/ j4 D6 l' [
  129.                     {& B$ d  y8 s9 C: Z' ]
  130.                         break;+ M9 _8 q) k* d$ B/ C, n
  131.                     }6 A7 {/ s* d; F; [% [) n
  132.                 }//while end! }9 K6 y2 X* u4 }) x* G, F& \- k
  133.             }
    ! t8 f* w1 N4 N# f8 l$ B; M
  134.             catch (Exception ex)% H' q& \. V' F4 B$ S' r
  135.             {; n; H9 Y% O' P" Q; v
  136.                 //整体异常处理$ s3 ^2 B6 _6 k$ ]  f' O9 k
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);0 E0 J' r8 ^) o. l5 t  t, x/ A- |
  138.             }
    ' T/ H' K  g3 W! V& ~+ O: y
  139.         }! d9 G( Y2 H9 A7 V
  140. 4 S6 U1 L5 L7 I, ]( n
  141. ! B8 U4 @0 G0 R" j6 @6 ~' x3 c/ K
  142.         public bool IsReusable" P$ @, t3 a! m" a
  143.         {, E' ]) F& `0 ~& L1 }0 [
  144.             get! G. l8 h* K" m6 a; W  l
  145.             {
    & v. ?/ B' z: n: L- t% _  O7 t
  146.                 return false;
    7 u% F0 e* k3 g. n
  147.             }1 k' K9 D7 ^) z. E
  148.         }! R( Q, a$ z, d3 [
  149.     }
    / m# A, ~* G8 J+ j1 u
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

: Y, W6 @) d+ L2 }- ?
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-1-30 15:55 , Processed in 0.060876 second(s), 23 queries .

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