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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

$ D" Y3 D/ U# p/ i* O( d: P
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    / A* ]9 S# U1 G/ n, z7 b6 B
  2. using System.Collections.Generic;& K0 _! U6 ~; ]; l( `  j
  3. using System.Linq;7 {% Z& L0 Z) w6 }, V, {
  4. using System.Net.WebSockets;/ l; N6 g  e) z  u7 n, D
  5. using System.Text;9 v% q5 }+ i4 G9 L8 e2 r% A* _
  6. using System.Threading;
    * }, h0 z! F$ F$ @% @" x
  7. using System.Threading.Tasks;# y9 W( C+ _8 W3 `  W4 U
  8. using System.Web;# m5 o" _4 d$ ]
  9. using System.Web.WebSockets;
    , Y# y1 h, e4 Y6 |* o2 D
  10. ) Y: w& X. L% h2 t) U
  11. 4 d1 k1 b! a7 ]) g& r& r) K% s
  12. namespace WebApplicationWebsocketHandler
    ( g+ C+ K/ ?7 u% I7 h) A. V5 y
  13. {6 t7 c: `2 C& j6 H
  14.     /// <summary>
    ' D4 F' T# w: x2 n2 \
  15.     /// 离线消息
    ; n# `8 U/ y3 ?/ w9 `) Z
  16.     /// </summary>
    0 a8 q# |; _1 Q$ M
  17.     public class MessageInfo
    7 ]/ b7 `5 L- Z4 s- [
  18.     {' e. o- Z! m# a6 P8 u3 u' V
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    . B2 K) x$ G! Q& r' u: f
  20.         {
    # B" T) s( q, a- I! M" E
  21.             MsgTime = _MsgTime;
    , l- N# x+ a$ \( N3 a
  22.             MsgContent = _MsgContent;
    4 f+ q% I. j% e$ K5 N' X
  23.         }$ e  O, Q/ m" o. n2 X5 @
  24.         public DateTime MsgTime { get; set; }
    " L0 X. @) m6 Y
  25.         public ArraySegment<byte> MsgContent { get; set; }
    0 B1 S# l( P6 N# a) U; n
  26.     }, K+ k5 x+ J  e% b" ~1 @) g
  27. 1 P' Z' n7 M( L+ q0 q

  28. # E) a; ~2 ]; W6 i
  29. ; t1 M0 j) W: g% R! N

  30.   ^* h& d1 y: w) F* ?  ~4 o1 T* a7 X
  31.     /// <summary>/ M$ [: l0 }5 [
  32.     /// Handler1 的摘要说明
    ' K8 o- Y0 a  Q
  33.     /// </summary>$ h/ ~" I. y8 F6 S3 B
  34.     public class Handler1 : IHttpHandler% B6 u! U9 A$ q4 o
  35.     {
    . Q4 N+ T4 B7 D  r$ n
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池6 S8 c3 ?( _) H& L' H" S
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    5 h6 ]  G  }9 H: A2 i4 z
  38.         public void ProcessRequest(HttpContext context)
    & [0 |' M; B" l" I
  39.         {
    ( k; l8 f* K3 s& f' w
  40.             //context.Response.ContentType = "text/plain";( ^: C( |9 h$ S5 n- T$ P. k) P6 e8 c
  41.             //context.Response.Write("Hello World");
    0 |. `1 X0 F" g! V7 V
  42.             if (context.IsWebSocketRequest)/ C; G8 W* M; n) K
  43.             {
    % _4 H; i) d# Z0 \4 |
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    & l  b+ q- e7 w2 d
  45.             }
    % |! W9 \5 H: }
  46.         }
    & o0 |, V) W* g) U. D8 |9 }. B- b

  47. : h' b2 z# V8 W5 p+ w
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    6 V& F; O' u. A* {& @
  49.         {; k3 r8 G3 A9 D
  50.             WebSocket socket = context.WebSocket;
    % e9 v! l3 v( M# z6 H
  51.             string user = context.QueryString["user"].ToString();1 I1 V' I3 H( B  M9 f% s: j& L! j
  52. 1 v4 R" e4 A" k
  53.             try2 F7 @( K1 t- [& ~
  54.             {
    1 [9 [" _! H. h2 \: w# ]& }
  55.                 #region 用户添加连接池
    : u# T; ^) K1 {+ }0 e
  56.                 //第一次open时,添加到连接池中
    ! q  V0 [% R9 d7 f" O+ `2 \
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    7 I& u0 W) I7 c$ B
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    $ G% z8 K) `& k/ Z5 c
  59.                 else1 h1 h  h. n# v4 U  Q$ V
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    / K& i/ M1 \4 O) ?6 g5 _9 o
  61.                         CONNECT_POOL[user] = socket;9 W4 ~9 P9 |- n* r. \
  62.                 #endregion: \: y9 Q7 T. d

  63. * u& \+ P8 N4 D2 z7 g6 k- [$ Y
  64.                 #region 离线消息处理
    6 W0 x  C8 O  T- F) O3 K
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    $ i- N/ [0 g  t5 `
  66.                 {# o: l  O9 g) y
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];5 y5 L9 \& q- n. f* p& S
  68.                     foreach (MessageInfo item in msgs)- k. J; {3 t+ v# i$ S* p3 J
  69.                     {
    0 g: _0 g+ R( m/ e- K1 C; `
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    0 X2 m5 v& k, c$ v  I5 x1 X6 G/ ~
  71.                     }
    6 C# r$ o8 |; `% X
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息8 }3 W( A. }5 ?$ X& X7 L
  73.                 }
    0 F) ]/ ]  M& ]% P
  74.                 #endregion9 V+ t# s6 V! r( c
  75. # B7 c3 J7 B. T# w. G- w
  76.                 string descUser = string.Empty;//目的用户
    ' n/ p# T* h- s/ ^- ~) H
  77.                 while (true)9 @, i2 x$ w* g0 g5 B6 z  w: _
  78.                 {
    " \# o! w, W' ^" M2 J) w, ~! L
  79.                     if (socket.State == WebSocketState.Open)/ Z# A  ~# }1 i& V" F
  80.                     {* G* S0 A/ [; U4 D% [! C
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    1 p# c& V4 S, h/ U# @
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    8 A$ I2 P1 N1 u. q4 P* f) |
  83. 7 v% C, Z/ r3 P" h
  84.                         #region 消息处理(字符截取、消息转发)
    % y! x1 E6 f& l4 }! t- Z% r
  85.                         try7 U3 d" E9 j7 P* w  i8 y8 q
  86.                         {
    , v) s6 }$ e( @
  87.                             #region 关闭Socket处理,删除连接池- G# w! i) b6 t3 A" F2 b+ I
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    2 m! ^  f$ z: [0 f
  89.                             {
    3 v$ p9 @  \0 p; W* p9 O
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池8 O# `5 w1 j% B# D* M$ J
  91.                                 break;1 O2 ^( _  ^. ?1 Z: J9 n
  92.                             }
    & Y" J' Q/ _/ o/ U
  93.                             #endregion! h, `9 x6 K* B+ e- _
  94. + R/ [/ i& f' D  u% Y
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    , y6 n. S5 C/ H0 C" Q6 q
  96.                             string[] msgList = userMsg.Split('|');
    * Y( n! o3 C+ H1 _2 V0 {
  97.                             if (msgList.Length == 2)
    & e. d! _0 s* @) U
  98.                             {
    . G; C) h4 y& i2 M8 C4 J9 d
  99.                                 if (msgList[0].Trim().Length > 0)2 T7 q2 P+ Q1 S# [% R
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    1 N: p& g/ K. U/ b! k6 `( z
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));) k' v1 ^9 k. N$ r9 h
  102.                             }
    4 j( n, p" x8 S% j" Z( J- @4 l; j
  103.                             else
    ( _* C5 `! s1 I( I& m( u9 S# N
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));1 R8 y6 j- W# F7 {

  105. # K: f5 `/ z- M2 B: J8 }# Y
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线- @7 d+ E+ |4 e+ T2 L8 u' n/ Y
  107.                             {
    / N6 \* N3 f' T
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    0 m% Z; K' r8 S+ c% F( b
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    + v' r' J9 ?6 n% M
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    ; N  a! [2 T/ u+ O: }! U8 f
  111.                             }2 _+ q% x" Z4 b& t  ]+ Z5 E
  112.                             else& N1 q  g; K: V" ~
  113.                             {
    2 p- @4 f+ `% V! f7 d! [
  114.                                 Task.Run(() =>  z3 V7 ^" f: r" P6 ?8 A  m
  115.                                 {
    ' _/ ]# O1 {( r$ V% h. O
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中9 G1 P# f) b  j# Z# ^% I* ?
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());9 n. T' V) T, m# o3 H! h" k3 _
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    " V: t6 j; f, X+ u4 u5 {& K) r' I
  119.                                 });
    . F* G; d; z: |9 B* [+ ~5 J! k
  120.                             }' |  A  H, ^/ D
  121.                         }
    8 v+ l5 u1 x0 f0 W) ^9 p7 f' V
  122.                         catch (Exception exs)/ Y% }7 }- C9 M% A
  123.                         {
    ; s3 b. A! i% M0 U: S4 `4 L" H
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    # u* w+ A. u% q& v) _
  125.                         }4 H0 Q; Q7 ]' ~5 e
  126.                         #endregion
    ' m, \1 G  O9 [' y6 [# t
  127.                     }! b8 e/ I' k4 p, A2 v* N
  128.                     else
    . w/ S4 p9 F( ^# @
  129.                     {* }. y& Y5 v) l# C, Q# Q9 D1 s0 @
  130.                         break;$ q, I2 h: ~1 `; X7 o
  131.                     }0 G  [3 h! n# w" M% F, O8 v
  132.                 }//while end% ?1 ~0 w* b& C( d' `+ x/ U) i
  133.             }& e% \6 ]' j* x5 T
  134.             catch (Exception ex)
    $ s- Z& R& O# O" R5 R# t
  135.             {
    3 K1 \6 O# H  j- r4 K0 a- K
  136.                 //整体异常处理
      u. [+ s! Y- h3 q2 ?( n" {; e
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    2 z% \1 S1 M( T2 ~$ ?8 I' z
  138.             }
    : ~% P. ~! C& Y; M
  139.         }
    * Z" o, {# S: M! U9 E. d9 F1 i, n+ i7 @
  140. ! W7 W7 d" U6 o$ o

  141. $ H$ T  U! S, f7 X% |9 T: t
  142.         public bool IsReusable' F* E3 l6 a' Z# i2 ?' H2 b4 l
  143.         {- w5 G: {8 n5 N- t8 ~( b/ j
  144.             get& o7 a, }+ f0 P% X8 D# l2 U3 y! {
  145.             {1 N$ X8 s8 i: b4 w( w9 c
  146.                 return false;6 V% x3 ]. X! y6 c0 d
  147.             }
      n" w5 x( N8 {, J4 T2 {! g6 e
  148.         }
    5 }6 ^4 C) i' e( o+ `; d" y
  149.     }# o7 B# x# N2 d3 L8 f/ c
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
9 P0 l6 o% H! j. K
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-12-22 20:08 , Processed in 0.101894 second(s), 22 queries .

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