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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

# K. t0 D, k; C) W+ P
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;7 ~, j4 {3 E6 J5 Q& r/ p
  2. using System.Collections.Generic;% ?2 A. k7 j  @1 I, V
  3. using System.Linq;
    0 e2 c9 H0 o0 r, k
  4. using System.Net.WebSockets;# Z+ N# o% h; I7 G+ X& f
  5. using System.Text;
    5 D! {9 b3 u5 B' C5 G6 k
  6. using System.Threading;' I5 V0 J! }6 T. }6 T" a
  7. using System.Threading.Tasks;! ^+ p8 |3 g! y; {
  8. using System.Web;7 d3 C1 {3 U1 J9 ]5 j; _% \& W9 p$ I
  9. using System.Web.WebSockets;3 m) i& J" D. _+ Z" P
  10. 4 w& o/ ]- H6 m

  11. # i! Y6 M0 U+ f0 x
  12. namespace WebApplicationWebsocketHandler/ N. l% {" T0 S1 z: W; p  a
  13. {
    9 |2 C9 G; C. ^. w- w7 w
  14.     /// <summary>
    # F0 y# P1 l6 e9 @% J  \
  15.     /// 离线消息3 |! F8 w- \% j7 C# |  Z/ Y- e
  16.     /// </summary>/ u" N$ T- ^( m* j/ I1 ^+ n
  17.     public class MessageInfo
    0 h/ ^% V7 E. Z+ k
  18.     {
    3 t) W" y# j3 L2 O  K% Q) n0 ?/ H
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent), f. Q7 i) X1 j' a( a/ O5 f
  20.         {
    2 o9 m2 k6 b6 k9 [6 V
  21.             MsgTime = _MsgTime;4 n8 |% T$ ?& n1 f4 `8 V  C
  22.             MsgContent = _MsgContent;
    ( |- h; ?. h: M1 t8 M; q- p
  23.         }
    1 d' j' I8 h# L3 V& `5 V
  24.         public DateTime MsgTime { get; set; }
    & L- [$ j& _! n2 I% R' p
  25.         public ArraySegment<byte> MsgContent { get; set; }
    ( @- |" e* v; L9 |
  26.     }
    : t# g: R& D* Q3 T
  27. 1 l1 Z( E3 Y. H* [; Z* k. ~, \% ?

  28. ) x8 K2 o( l7 T# R7 f

  29. 6 G8 B% i; x! W9 ^
  30. $ G6 ~' c% y1 A2 i
  31.     /// <summary>6 T( N) g! Z, `' [
  32.     /// Handler1 的摘要说明
    $ a1 }" Z6 V3 u1 m. t  B$ q2 m
  33.     /// </summary>% b5 w. a' G# u$ r* o7 I" ]8 G' V
  34.     public class Handler1 : IHttpHandler
    + ~' w8 N- n2 S
  35.     {6 j, t, w1 n, W
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池9 ?$ h3 X$ a+ H
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    % E" A6 K# Y! B* T2 c
  38.         public void ProcessRequest(HttpContext context)
    0 b1 O* T2 t- }3 M' D+ @+ _3 E# P% {
  39.         {
    # x; g0 |8 J; D' U& D% o
  40.             //context.Response.ContentType = "text/plain";
    * o* p( g, @( E& u3 T, z
  41.             //context.Response.Write("Hello World");6 v- c& b/ `4 L) l1 E. L- L
  42.             if (context.IsWebSocketRequest)
    + {1 q" t3 y& v3 y0 f- y1 n1 R5 ?
  43.             {" K' M9 [% o- k1 R
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    1 w$ X: a; B6 M) B4 a
  45.             } 3 r4 j, S& |' t: O  Y, N# ~: v
  46.         }
    ) e/ X2 W, ?! h1 H' p4 ?1 t
  47. * r: }6 Y& d9 a8 l% T4 i
  48.         private async Task ProcessChat(AspNetWebSocketContext context)0 S5 o. ?7 t) k1 W* H% }. D  H
  49.         {
    ; v2 w% a- a  |$ S
  50.             WebSocket socket = context.WebSocket;4 G" e2 r5 [3 Z# h; C
  51.             string user = context.QueryString["user"].ToString();, A: h9 H# `) Y% r
  52. 5 w/ a! M- u# }& l' R3 Q
  53.             try
      ]% O! `1 @$ o
  54.             {+ T  N0 F4 f. t* C
  55.                 #region 用户添加连接池# V& \$ t# ]$ S! w
  56.                 //第一次open时,添加到连接池中: l+ A' p2 n8 Z! Z  f1 d
  57.                 if (!CONNECT_POOL.ContainsKey(user))( T0 ~( |4 z8 b1 C/ X
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加" V* v5 ~+ A9 w! O2 ^9 g; |
  59.                 else
    , K" a% @# j: B5 }( a
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新' B" E, w* H2 v& z
  61.                         CONNECT_POOL[user] = socket;
    2 V% `5 f, y5 N- ^( i
  62.                 #endregion
    / d/ v/ t8 X) c. m0 S, C
  63. / v$ ^* k2 B0 U2 Z8 q& U! O6 ?1 \
  64.                 #region 离线消息处理
    % n" _3 y* Q, f
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    * r: I/ t0 o' U$ e
  66.                 {2 n0 {9 T1 }2 u
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];  i" l+ @' I, k+ K) \3 Y7 z: Z
  68.                     foreach (MessageInfo item in msgs)
    * |2 ^' b7 S; t
  69.                     {
    $ P1 l- q, P$ k
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);5 \4 S( N" F6 h) l$ a9 S
  71.                     }% _( i! E* I4 J
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息9 G1 i9 G3 O8 P. q* m
  73.                 }
    2 a! r: P! w4 X; @( j- h! m
  74.                 #endregion  n9 R$ {- }4 Z

  75. . i* B" l$ W+ d9 G& y2 s" B+ `+ i
  76.                 string descUser = string.Empty;//目的用户& G3 s! r: [' s- e
  77.                 while (true)2 ^( u# e1 W+ N
  78.                 {
    ' A5 `1 e1 q% D, a9 C. d" O
  79.                     if (socket.State == WebSocketState.Open)
    / E8 _; ~( F# H" B1 i) W& I
  80.                     {
    3 `5 a( D* T1 D' T5 f! D
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);5 H& h" `( h2 g) O  Y! D9 |
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);% e; p( A2 |/ R& f- U" d! W" ?, b
  83. / n+ w0 u; O) d3 u+ t9 X; T
  84.                         #region 消息处理(字符截取、消息转发)
    / V* k6 h* @+ F2 T
  85.                         try
    3 J' Y% M! c$ l$ R) r9 C: ~
  86.                         {
    $ A8 W# Q* I! B  M% C
  87.                             #region 关闭Socket处理,删除连接池
    7 g1 `5 E2 I; J# ?8 u$ _! n
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    * V* P: d  J' d' x& O
  89.                             {
    7 E8 e# }; R& O( Q' l$ K5 [# E5 Z
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池0 s) p7 K4 G! Z! N3 H
  91.                                 break;
    8 t8 {4 ~0 c/ i- S) _/ f6 d$ g
  92.                             }3 q/ n4 c- G9 O3 }2 D3 q, p' e
  93.                             #endregion8 r- g0 B% `7 d
  94. , o# D" |$ m- N, B. l4 n
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息- r$ A# O' N: e' \! G6 [
  96.                             string[] msgList = userMsg.Split('|');
    ; o4 j, I" C) q. B' L) q
  97.                             if (msgList.Length == 2)
    4 W2 Z+ Y3 ^- \, }
  98.                             {
    . x/ m2 O0 A) ^0 t
  99.                                 if (msgList[0].Trim().Length > 0)1 j3 o- Q/ _+ p) x; T, Y6 w
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    ' p! L9 Y5 `/ J) ^
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    9 \8 F( z9 r) e* U$ |% H  t
  102.                             }
    6 o3 ~% w/ y; U1 ^. K
  103.                             else
      I9 k/ w% L) |& J
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));+ Z" T/ R- @- V
  105. 2 G$ _. P" W  s
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线7 Y" [6 c  `6 @- T. C
  107.                             {2 i! d" x. o& g) e; `* \
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端9 n9 V5 z- N: o& f
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)  j% V7 @' V2 v) e5 L
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    6 B  n4 q& N2 j# ~; W$ N
  111.                             }
    . Y3 n" ]" a' K& w' d$ ^3 Z
  112.                             else
    " \( o8 n$ s* ]
  113.                             {
    + o+ O' J8 ~2 l9 \8 B3 i7 P8 w& y
  114.                                 Task.Run(() =>- q. Y. o! ]/ e8 C! x
  115.                                 {
    5 q' b  n  q6 f( Y
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    ( O1 `2 C, ]0 W+ ]7 j/ P8 Y
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    % A- `, g: X! Z
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    ! ]' v" \. N8 V& s$ n
  119.                                 });. r. k: z- l7 ~0 W
  120.                             }6 Q& l) s, T  W2 [% Y
  121.                         }
    5 ~: ~8 |, R) Y1 @5 D
  122.                         catch (Exception exs)2 X, i  N7 A! s/ a* G- e
  123.                         {9 s) _# H) H: _
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    6 F" |7 s4 ?, _4 \: b' G7 k8 w& v& k
  125.                         }
    / ~' e" y  [: F4 z; h5 }  \, b
  126.                         #endregion2 W! h' O7 g* V! a* P
  127.                     }! |$ h5 d8 ?$ d! o0 t1 i  Q6 o
  128.                     else
    * Y4 y3 N" c! p, \& ~; ]. L
  129.                     {
    ; ], ?4 ^6 D) [1 d' m
  130.                         break;
    6 ^0 D- C# H0 x3 `* D
  131.                     }* `( d6 o' B; x6 a3 u0 Q9 X/ C% P
  132.                 }//while end0 b0 P0 m1 j0 H
  133.             }
    / V" t& q! Q7 Z8 G" V2 t
  134.             catch (Exception ex)
    4 G% _2 L. s+ J4 K% Q( ~
  135.             {
      V( o# [# f% P2 d9 E2 T* H
  136.                 //整体异常处理( s- B+ j  U! A6 _$ b  `
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);4 S9 a2 n5 v$ x# E' D3 `# I
  138.             }) r& T$ F; R1 J  G6 g
  139.         }
    , M8 C; ^% @0 U1 c4 B

  140. 2 T) F4 _$ f! Q& D

  141. * N; ?; B. E+ W! a5 G! n
  142.         public bool IsReusable% O& Q+ J: y2 r  E0 _$ T
  143.         {
    ) \7 |9 z! K3 W4 o9 X# y0 v
  144.             get2 @5 Z4 Q$ ^8 ]& |& F7 ?# h
  145.             {' C% J$ n! S* s7 `  M# d
  146.                 return false;, S  r- R9 W2 J  f& A
  147.             }
    7 h* M' x' b# L, q0 `
  148.         }1 z1 x! Q$ v) E3 W
  149.     }
    1 j7 e! c+ _& K: y9 L4 Q: I
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
+ J' h! A# i  j2 a( e% w0 W
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-9-21 03:13 , Processed in 0.090616 second(s), 22 queries .

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