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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

# m$ K4 l1 B& i* L4 z
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    : x/ _" i+ {- Y
  2. using System.Collections.Generic;6 X, N* d0 M" X, F! B1 o7 O
  3. using System.Linq;2 y5 J9 }% I- J6 ?* y4 d
  4. using System.Net.WebSockets;" d/ S- O: [$ e, O$ V+ d
  5. using System.Text;
    ) f  y" A' D# o$ I7 C
  6. using System.Threading;7 p+ i5 X$ o, I7 H( ]
  7. using System.Threading.Tasks;
    7 J; W& O. l- n5 p; J( y
  8. using System.Web;) }: A3 y2 E) l# {7 l( w7 d  z
  9. using System.Web.WebSockets;
    5 B- ~+ o- [7 _9 P
  10. 5 Q0 j2 r' c( t, K% h

  11.   q9 ?9 x5 u9 }  j& J
  12. namespace WebApplicationWebsocketHandler
      i; D' y, S; F+ A( f
  13. {$ }7 G7 f0 u! {, ]9 O3 M2 i
  14.     /// <summary>3 D* v/ c; X2 E" o  R4 h
  15.     /// 离线消息$ Z5 f6 C9 ?! J5 F( Q) X7 L+ W
  16.     /// </summary>
    . Z9 ]$ n4 J$ O8 U
  17.     public class MessageInfo
    # x5 `2 _: j3 s  g1 Q
  18.     {
    ) {0 q+ f) H- h% \6 u( i3 e
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    / b! z3 P& z9 J( h7 H
  20.         {4 K% F# g. T. s1 C) u
  21.             MsgTime = _MsgTime;
    + M3 C1 P  q( O6 p6 c
  22.             MsgContent = _MsgContent;
    6 ~0 \1 e9 k( J7 j
  23.         }2 D7 k; o6 p# x( B) x: I
  24.         public DateTime MsgTime { get; set; }
    & J: H" @4 Y. b' t# Q2 Q: z
  25.         public ArraySegment<byte> MsgContent { get; set; }
    . z$ L: |0 S: a+ u
  26.     }
    ' @  W2 }6 o/ F, o: L

  27. 0 `8 o' j& D- w* ?8 N

  28. 2 K8 d* t) \- Q3 H, \* J
  29. + M+ g! @: X' i2 b% f, W3 W& v
  30. 3 [. j! v- }! r( U: J
  31.     /// <summary>, n& E  n1 y$ ?$ L; A
  32.     /// Handler1 的摘要说明
    ; f4 c$ K3 ?/ Y( b6 q* O, K7 U
  33.     /// </summary>
    ; _; {# ?2 y# Z; ~+ o+ F
  34.     public class Handler1 : IHttpHandler
    : z% m* ]& }: [' p4 n2 I
  35.     {
    7 U1 W. g: x, _* o) ^% v
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    ! u' p8 d" F- c
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池. B6 f! [% B, `7 ^  n( ^, o4 F
  38.         public void ProcessRequest(HttpContext context)
    6 L/ P2 Z/ Z, g; ]# J! Z% ]' C
  39.         {3 J* v% S7 ]. w+ Z' b0 r
  40.             //context.Response.ContentType = "text/plain";1 u' h% v( ?& `
  41.             //context.Response.Write("Hello World");
    / d+ O* {2 {& r+ T) h1 }. d
  42.             if (context.IsWebSocketRequest)
    9 w/ C4 V- o# L: G2 k! T: I" ]
  43.             {
    " a9 }& t! v* C
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    $ @6 I' j& `' P
  45.             } / C* n% D2 L) F1 h- Q* U2 A
  46.         }
    5 l8 H2 l% K9 t& [* T2 R
  47. . U# t: n& z/ ~2 c
  48.         private async Task ProcessChat(AspNetWebSocketContext context)& s5 M4 V5 x! g
  49.         {
    ( w# K6 ^( D! U2 `' y0 P8 M3 X1 ?( N
  50.             WebSocket socket = context.WebSocket;! }* I9 X" r) R) z
  51.             string user = context.QueryString["user"].ToString();
    $ }# \5 P' ^2 _6 F; c

  52. 6 K2 s4 d: \& D4 g0 T+ G: ^
  53.             try  P  i+ }, m. `. Q: G) v
  54.             {1 ~' B1 Y8 h2 K' j/ K/ B8 e4 l) a
  55.                 #region 用户添加连接池( M% d! a" L4 g* ?
  56.                 //第一次open时,添加到连接池中
    2 s- l2 C! ^- k2 N
  57.                 if (!CONNECT_POOL.ContainsKey(user)), z3 l8 j/ E8 \$ J8 F- t
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加2 F9 W1 r; e! W  d
  59.                 else  P/ m. k* Y+ e2 `; F8 ?7 {
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    2 e0 R+ M. I: B7 N
  61.                         CONNECT_POOL[user] = socket;! I; h. q* u; u9 o. b; l  p5 g( |
  62.                 #endregion
    & }7 _( ?8 P5 L& u7 q

  63. - u8 i$ [/ Y/ Y+ D" G
  64.                 #region 离线消息处理2 x; F6 r# @6 r( M
  65.                 if (MESSAGE_POOL.ContainsKey(user))% n4 N/ Q. d4 \8 u3 F
  66.                 {
    ) u- k) J9 z: S
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];  a# E3 Q7 S# b: _# V/ s* Z( H
  68.                     foreach (MessageInfo item in msgs)
    7 [6 D$ k% l4 y
  69.                     {9 @* q+ v% U4 d3 R4 F
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    7 [0 F0 M8 W7 X1 f+ e
  71.                     }
    ! i3 }8 ^. w+ }) V+ ~: C) p; O
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    6 Y" A! z, f; a
  73.                 }! d0 N  x; f- ]1 O- i, \) }( a
  74.                 #endregion
    1 a% p, _. K7 O$ M

  75. 5 I2 I4 A  ]6 _/ c2 S1 `5 ^+ S' @
  76.                 string descUser = string.Empty;//目的用户' L6 [$ R% g0 {0 L# o1 G* ~4 ^3 }+ o
  77.                 while (true)
      z' W, }+ o" }. @! ?5 b4 `. U
  78.                 {! e. B6 i1 e, F  O  `
  79.                     if (socket.State == WebSocketState.Open)
    0 V3 D+ U9 `5 |3 p& ^9 D
  80.                     {
    0 ^: H& I2 ~1 e# m
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    ! {+ v; s% S0 T. N) ?2 u) R* n
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);2 L1 Y" s* E& v$ {2 d; q. Q2 \
  83. : t/ A# W7 ~# N4 L' d9 {/ o
  84.                         #region 消息处理(字符截取、消息转发)
    ! T& M! W5 j, j# H) C1 r
  85.                         try4 f- M* R9 ]0 r
  86.                         {* I+ B" [6 A3 I- I5 \
  87.                             #region 关闭Socket处理,删除连接池
    : R( o. \" H7 o$ L; H9 B0 V. I
  88.                             if (socket.State != WebSocketState.Open)//连接关闭6 n8 `+ P# `( S0 R8 n' C
  89.                             {3 f; u* N" B8 ~. I
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池: B) L+ k/ v' C
  91.                                 break;" ~& h  C1 j+ r# S- k7 U4 x2 x! q
  92.                             }
    1 Y) n% N  y0 `. {5 w
  93.                             #endregion
    ) g9 v% V/ `* ]
  94. / z% S* ]. e3 }
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    ) W) J  b+ y( C& N
  96.                             string[] msgList = userMsg.Split('|');
    1 h6 Y6 M8 P/ v  T" J  c/ ?1 n  n; B
  97.                             if (msgList.Length == 2), S/ B- z( V3 U' b, h( ~2 n
  98.                             {' k0 v$ b+ d7 C6 Z' E- Y
  99.                                 if (msgList[0].Trim().Length > 0)8 q2 n$ H: d. X% L0 @1 i( v
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户# [2 L0 @9 v, {+ E% Z& W
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    ) U8 s2 n. v  P% B5 ?$ B
  102.                             }
    $ k: [) @9 t; D9 {, J
  103.                             else( I% q# Z7 B+ m/ ?2 E. ]
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    : e0 }& w2 G* E: h. ^) O  p8 p( U

  105. 7 ?( V/ I  J; J# J- C: [' w
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线7 D8 [9 J. J# Z& x
  107.                             {2 W3 I2 r  O7 g8 R
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    * K0 g. k, X, z* n' t; Y2 Y
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    . X4 s- _5 `7 }/ G$ V8 }' y  c
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    % z: F# E2 ?% C) l
  111.                             }
    9 D* T7 q4 Z. I9 M8 N) ]7 e
  112.                             else1 t& r4 U. X7 P- C& p/ P& ?! Y$ N
  113.                             {7 O2 W/ F1 Y3 I1 M0 x5 z8 K
  114.                                 Task.Run(() =>
    & R: D' n9 X, ~: a4 [& a3 O
  115.                                 {2 _2 |# N# [6 f7 v
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中5 X5 g* A0 X! ]5 R+ P
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    1 u* d9 g2 a6 S/ Q( @+ F
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息9 k  B5 }2 [$ H: S- D
  119.                                 });
    ' q" O" ^$ |' d& J- u5 }. ]# e/ `# Q
  120.                             }+ l& u* h" y& N' C- e7 d/ Q& u: ]
  121.                         }7 Y2 P" C+ ?9 p& {1 W6 u9 c% `* F
  122.                         catch (Exception exs)8 f/ u8 F: q' g' E: `% j: {
  123.                         {
    & P: J! s5 _/ L
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息1 g& i( N+ ]+ b8 ]9 {% r  a3 a/ H
  125.                         }
    9 P5 n$ b) ]" @/ d2 F
  126.                         #endregion9 e% V5 N% ^2 R0 j
  127.                     }
    4 }& M3 d5 d; ~" J$ V3 o
  128.                     else  l( j. r  B" ]7 b' x7 {: R- p
  129.                     {" {# J9 n- r7 g1 p8 |* g' U
  130.                         break;
    ' Z, q  U, c4 k+ R$ m) {7 A. _7 h
  131.                     }
    , q* h0 i5 J! H% C+ J. w
  132.                 }//while end
    " C3 s" f& C2 z2 h
  133.             }
    3 G8 c( B( E8 O* U
  134.             catch (Exception ex)  M* W0 `) o- Z6 v+ o
  135.             {" `" [1 T% T; T+ x1 n& w+ d
  136.                 //整体异常处理
    & b2 z/ [2 a0 U) U5 P
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);$ h( ]8 |( w  n/ O3 R- s* _, z& S
  138.             }: s4 v* B$ x/ i. _4 R
  139.         }
    6 t& {6 s" j2 a  G! K  ]3 g: O6 H- \

  140. , V: |  B: [& S9 i4 I: q
  141. ) O6 e$ X9 |5 R4 l- B1 w
  142.         public bool IsReusable
      F" r( e0 d( g' Q9 D' ]! t* z
  143.         {. ]% n% N% s4 P( Y
  144.             get
    . u+ t# n7 U; `5 p/ Q& m
  145.             {
    7 F# }/ d$ ]) t3 k5 e+ ^
  146.                 return false;. ]7 L2 i: G3 k4 S
  147.             }8 n/ Y$ s% q. r1 V$ X8 H6 X
  148.         }8 h: e/ g: n$ e" h: U$ f
  149.     }
    + K8 `) M8 w* z% j( \' Q: c
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

: m5 }6 N- l1 }5 p
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-3-16 18:53 , Processed in 0.074952 second(s), 22 queries .

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