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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

, J6 Z1 p0 `0 B& A  e" H1 G
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    / [4 Y" i0 C* `8 f) G
  2. using System.Collections.Generic;
    & _  U# E# p- b; x8 w2 N
  3. using System.Linq;
    ( D7 L( _" P. `6 W- }- T. }
  4. using System.Net.WebSockets;
    + @& B- i& o4 O2 Y2 R3 r1 h
  5. using System.Text;
    7 P4 y/ y7 O( C/ a4 E+ h# l4 f
  6. using System.Threading;
    ) t; A  c3 F* m! X9 J- B
  7. using System.Threading.Tasks;
    * D3 ^! b1 C5 d' v$ B* B; Z' p
  8. using System.Web;6 o2 E* L! [' Y- V% E. k# r
  9. using System.Web.WebSockets;1 v1 Q' O% }3 }

  10. : E+ b5 K4 V; F4 H9 ]. v# E7 ^9 b
  11. 1 H) J( s! o' t( b' q
  12. namespace WebApplicationWebsocketHandler0 h. w7 x7 I5 w( f1 @3 ]# d, p
  13. {
    9 E2 C) c& V6 v, J6 C; Q! z5 Y
  14.     /// <summary>, b' s: h& y7 N! w# q
  15.     /// 离线消息7 I' ?1 i. l4 E" R7 U: E
  16.     /// </summary>
    ' J: f3 E1 Q4 C$ _: H# `. o
  17.     public class MessageInfo
    ; A6 R8 q  l5 B8 e
  18.     {
    * t& f/ U# p2 n- f
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)* z& y) X; o- ~+ P
  20.         {
    + [8 O0 ?+ `4 `; m$ p
  21.             MsgTime = _MsgTime;
    3 z$ z, |, ^8 `
  22.             MsgContent = _MsgContent;
    5 u$ d2 a! Y' H
  23.         }  [6 r' ~$ L) A3 N
  24.         public DateTime MsgTime { get; set; }
    ( M" c4 ^7 G) L* E/ @
  25.         public ArraySegment<byte> MsgContent { get; set; }/ W9 T6 k' y% K6 |3 E  M0 G
  26.     }' K: F- x+ ~2 F* D

  27. $ j* N/ A3 j8 z: s6 X' c, F
  28. / i4 D% o# h) I4 K

  29. 1 |* [7 L8 Y9 |4 z
  30. ; `8 {+ @& m3 B9 w
  31.     /// <summary>
    2 c$ T1 p! e3 x* H9 ?6 w
  32.     /// Handler1 的摘要说明( \8 N/ {8 y  r: G5 B
  33.     /// </summary>  j# d6 k1 Z3 f  l- u
  34.     public class Handler1 : IHttpHandler$ C7 P. c) ~; q
  35.     {
    - A6 V* H. b+ W* _6 ^# _/ k
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    " U& l( Y% L+ K+ l/ Z
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    $ o) M# A4 A" a
  38.         public void ProcessRequest(HttpContext context): i, }1 ^3 S  Z6 E* m3 q" D
  39.         {8 w. Q3 t# r5 ?: q, W! m
  40.             //context.Response.ContentType = "text/plain";+ ?# u3 m# e' ]5 e
  41.             //context.Response.Write("Hello World");# _5 G% |- j! v3 ?
  42.             if (context.IsWebSocketRequest)
    8 d, J4 u9 T: z( V  r0 J) `0 Z
  43.             {( E* M2 i( X5 v% U. Q
  44.                 context.AcceptWebSocketRequest(ProcessChat);2 T9 t8 E6 t) Q5 O
  45.             }
    ! {6 S1 c3 b. T6 j8 }' u  _
  46.         }
    7 m# {# ^5 j3 K8 }

  47. + Q; m6 Y$ B: q+ @) _
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    " h, j3 |4 L0 j- n: E2 M7 M
  49.         {
    " }7 T4 Z% x+ H* o% p2 W# ^
  50.             WebSocket socket = context.WebSocket;
    & w' O3 I6 x: ^! n
  51.             string user = context.QueryString["user"].ToString();
    8 Y; ]" Q% D  P1 n( O
  52. , U2 J( w( {* ]- M( C1 n" R
  53.             try
    5 q1 ~' [3 v6 ]8 h+ Q1 {
  54.             {
    ' x- D; z1 P- \1 q3 G
  55.                 #region 用户添加连接池% ]& v* k( U! @, r* I
  56.                 //第一次open时,添加到连接池中# S* D; ]: E0 ?7 F  R9 ?% L
  57.                 if (!CONNECT_POOL.ContainsKey(user))( M: \, Z: ~! k4 K
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加$ d2 f  r* K' v# T+ c" x1 i. c& N: y* i
  59.                 else
    5 V3 n" d3 E6 J$ N! k8 C$ N; w2 D
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新  w. I! u$ F0 m2 L# G" n3 D
  61.                         CONNECT_POOL[user] = socket;1 m" G# C) s4 f3 f7 U1 R% Z; G
  62.                 #endregion* F. h3 f; \4 k

  63. 6 c- }; V9 k  ?. C0 Q7 r
  64.                 #region 离线消息处理) P4 U: K0 e1 Z7 b% ?9 k' Y+ y- }! M8 H( I
  65.                 if (MESSAGE_POOL.ContainsKey(user))) v! a" R: |( U; O( B
  66.                 {# d3 _/ @# w: P/ }' q- A4 ^  @! N
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    2 I+ }$ c# |0 S$ ^: r
  68.                     foreach (MessageInfo item in msgs)
    , k5 L7 O# J, u& i( s" [/ X
  69.                     {7 ^7 q* @/ w4 Z" q
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    . R) k6 Q+ ]; x  L6 i, P+ Z3 Y
  71.                     }2 M3 w& j3 a' p
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息. Y8 B' x; i- S' V1 ]4 d+ P
  73.                 }
    " L" ~& [$ ^$ X3 T! T( B5 N0 W, }
  74.                 #endregion2 l5 {- ~. ^% e$ B; O6 V# o+ y& Q' l' a

  75.   `+ s( p# Z. K7 x) z% |6 f1 \
  76.                 string descUser = string.Empty;//目的用户7 _2 n. [; W$ w0 S6 |
  77.                 while (true)* ]! E4 B8 ^( [! M7 w$ K4 Z( ?
  78.                 {$ X7 \6 e8 J1 E: ?- B9 u
  79.                     if (socket.State == WebSocketState.Open)9 t" x$ U+ ^* Y! w2 Y
  80.                     {7 l; i& ^1 A! L& M' C1 T
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    - Z; W7 U$ T/ @: T4 ]/ Y
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    - k! {' c% _  R7 k9 q  w2 ~

  83. : i% X, H5 J  a4 a
  84.                         #region 消息处理(字符截取、消息转发)
    4 _, c& n! U, Y" n
  85.                         try' z1 a, K& a- w+ r0 k& U  ]& h
  86.                         {
    + T+ n9 {& s# e# [
  87.                             #region 关闭Socket处理,删除连接池' e; G, z9 F- l' [. {; w1 h
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    8 Y5 k3 {' O: Z* C
  89.                             {8 s; L; }* z) [/ q- e
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    8 V" F" L& L' g1 M: \& T
  91.                                 break;
    : s) F- L2 L6 K: x
  92.                             }- W; m& t& S: z# ~/ A2 x+ G
  93.                             #endregion
    / Y6 z; l  t, Z
  94. - Z% H, F( j3 t! F+ r7 x
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    % R3 p4 S9 z/ O9 }* [
  96.                             string[] msgList = userMsg.Split('|');8 E  _- E$ y5 e* B
  97.                             if (msgList.Length == 2)" o4 `3 G! `4 C# [
  98.                             {
    8 D! M# ~& ^. J9 }* O4 J* k
  99.                                 if (msgList[0].Trim().Length > 0)
    1 p  m7 H* I: B0 n: _
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户! M. r: z1 p$ j+ ^
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));# ^; ?6 w' g+ q4 y! {: _# E# Q7 r7 v
  102.                             }
    9 W0 p1 B0 t( o& a5 Q- g) `- P: ^
  103.                             else9 d4 V8 a$ p8 a# a' ~/ f1 j' C$ z
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));/ p7 d) a$ i0 w( R

  105. ; W) B: |" Z: b0 g4 U  D
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    3 n4 W9 Q5 g- c# E& w
  107.                             {" [1 \) h, l, K' ~5 G
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端( ^$ A- J+ ^! O6 B. ?! E
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    0 t1 Z6 w; |' T7 V
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);5 h2 N4 @- l( f" H/ t( t# i/ t4 m
  111.                             }8 e1 W# c" T) Q! o+ Q
  112.                             else! ]: W2 b3 N' f8 ^; H9 s
  113.                             {6 `0 E+ r5 @1 H0 l, }6 {3 V, z
  114.                                 Task.Run(() =>8 [# Q' o; f4 Z+ b' q& n. Z- j
  115.                                 {
    % F) Q# u* D# \" C" F7 O9 {2 q% ~
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
      z& U# z4 x% W5 k2 x6 z6 d
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    & c$ [) [2 p- R# J6 v2 n
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    6 f+ q) `' p, t, i9 g" i
  119.                                 });
    1 m5 O8 c% K' M5 m
  120.                             }; }* W. l; r. b1 x" u
  121.                         }- m7 I4 r) t' E- z1 R8 m- K( Z
  122.                         catch (Exception exs)
    ) ~" V5 k+ K: N! l6 E
  123.                         {
    1 f* O' _5 f' e+ V" h+ S  H3 C
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息& _+ e  h" i/ g
  125.                         }
    , Z/ u0 y: f: x& Y
  126.                         #endregion
    ) ]4 T8 J. u" g: N' x6 a& W
  127.                     }
    : \( r* I5 D; w/ I$ E) i& s) T5 _
  128.                     else! A# H9 G0 b/ U8 j7 R6 r
  129.                     {
      o/ a. {+ n5 E; w
  130.                         break;
    2 O! K3 z" j% l8 T+ V* S# r& n
  131.                     }
    5 _; [3 ~( F3 C
  132.                 }//while end
    3 ?$ V1 W2 Z8 X
  133.             }
    ! G1 u* i) ?2 S! k( d
  134.             catch (Exception ex)- ]' c- K' I( Y/ ^) p9 o2 o+ Q$ B
  135.             {
    / H) U! Z: E0 i
  136.                 //整体异常处理
    ( f/ f7 }  F& T" P) J7 C% K
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);" O) j- o7 R* d6 f) w: b4 Z2 G
  138.             }
    7 E2 k$ T8 E0 }( I3 k6 U- b( V; o
  139.         }# w; k$ t+ ]) s4 G6 G/ a7 c
  140. . r( q" r+ }3 [8 |
  141. ; X5 N( P$ Z$ M% q% q/ F% K
  142.         public bool IsReusable( E. q0 |# T5 M1 p7 t% h, a( Y
  143.         {: D* S, q* K0 O* z) A9 i+ {
  144.             get5 C0 |* C6 C- d) z$ s
  145.             {
    : {  C6 V9 [% Q: G% z
  146.                 return false;: J$ U3 m# @: F
  147.             }) N$ k: J( Q; R. @) n
  148.         }
    8 G! f# h& b$ y* [% i, {
  149.     }
    & w( @5 N0 X8 o7 e+ J& v
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

- c  n% k$ R0 a) I0 r
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-4-30 19:58 , Processed in 0.055125 second(s), 23 queries .

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