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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
: e3 Z& j5 _& k% a4 |; V" p/ }" Z
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;; A* Y5 [6 S, U5 s0 E
  2. using System.Collections.Generic;5 g7 n. V( l- O6 T) c6 V
  3. using System.Linq;
    % E0 z- N5 R* e& Q& N; t
  4. using System.Net.WebSockets;3 _4 H% z2 ^# e4 Z9 g. U
  5. using System.Text;/ p" l  Z# U/ L
  6. using System.Threading;" @& u2 x$ a. [& ^5 N5 Z* E# m4 w
  7. using System.Threading.Tasks;
    & Z  d# ], d8 W+ B/ d% V
  8. using System.Web;! y( M# F/ V4 u
  9. using System.Web.WebSockets;
    $ B' V; Y* e2 @: L: B
  10. 0 y- ]1 t9 f$ N; |  j6 F1 R, T# q+ a; f
  11. 1 P3 e! C2 }, v
  12. namespace WebApplicationWebsocketHandler
    ) O" e  u: R) V$ v# |8 h, h, }% G5 N
  13. {2 `: {' Y8 L/ N$ _# B
  14.     /// <summary>/ n; u; y8 j4 R, S; e: l' I
  15.     /// 离线消息
    , |! q* a. I0 G% _3 [) @4 Y, x; g
  16.     /// </summary>
    8 v* L9 x" H% h5 O( j
  17.     public class MessageInfo# q5 u7 L: |# C( h
  18.     {0 u+ v2 c9 T+ j9 s3 U. F% n$ s  R
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    ( w9 c$ [: Q4 h& C/ c7 o  ~
  20.         {  r$ v6 ]) }" H5 y8 D
  21.             MsgTime = _MsgTime;
    3 y. M8 _' ]0 y: Q0 p  Y
  22.             MsgContent = _MsgContent;
    5 R& t  J! A6 a; d# Q3 F) ^  j6 F: `
  23.         }% V5 e; D# P& O3 c4 g' {3 U7 F
  24.         public DateTime MsgTime { get; set; }
    , n9 B) ~7 B+ y' `2 z! }
  25.         public ArraySegment<byte> MsgContent { get; set; }$ z9 }3 e0 k  l9 H' O% I
  26.     }
    4 |; d" G. r, q6 Q) j' f, A
  27. * M6 |3 |- x! s3 E( r  O/ m8 }% D
  28. ! v# U! Q9 `5 O2 q5 `* X
  29. + c; P; s8 g4 _- C

  30. & D: m  @7 S" z- J5 O; T! {7 w
  31.     /// <summary>, H/ `; h8 o& G$ F9 e( \: d0 ~. R
  32.     /// Handler1 的摘要说明
    9 }+ _. g# m5 w" J7 J  z! _
  33.     /// </summary>
    & w% S% z9 E) Q" D% g
  34.     public class Handler1 : IHttpHandler9 a0 I7 E$ G! c: O$ K; R$ X
  35.     {, P. m, r, s- z, V
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池- P- U1 C/ p1 \1 f
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池$ i% m- R: M- @" F. C
  38.         public void ProcessRequest(HttpContext context)
    5 B2 R) M7 F0 H: X4 G. r% y
  39.         {
      ?) z. F) O/ P5 ~
  40.             //context.Response.ContentType = "text/plain";
      e) }# u4 f* f  X0 _$ }0 v; k
  41.             //context.Response.Write("Hello World");$ g4 @* r( ]; z4 H2 A6 U: p- J
  42.             if (context.IsWebSocketRequest)" u, |2 K' H, _7 X+ H1 |7 w' c
  43.             {
    6 l) H* w! ?" H0 q, M+ J$ U
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    1 z* g" Y: O) x
  45.             }
    " R7 i/ W6 o+ P
  46.         }  t* k  F! ^7 E) z& O- b8 h% b
  47. ' n! C  G* Y3 @2 u: r( u4 I
  48.         private async Task ProcessChat(AspNetWebSocketContext context)7 }5 A6 g* y1 F) _& h
  49.         {  d9 V0 Y" z* g# l0 R
  50.             WebSocket socket = context.WebSocket;
    5 @& M+ ]0 O8 G/ w5 ?4 U
  51.             string user = context.QueryString["user"].ToString();
    7 |: D3 [5 E; i3 R( ^
  52. $ g" l2 A! Z0 `) I  v
  53.             try
    * K5 V% `: m% b, C
  54.             {3 @% l( ?0 h- |! L) m
  55.                 #region 用户添加连接池
    # K: R; X  a6 z# Z6 @( b$ S% k
  56.                 //第一次open时,添加到连接池中
    # P# u1 D; Y" S7 s( Z/ r% M4 n2 I
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    ' o- ^$ y' y4 f( q$ O' G& N
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    6 T3 ^9 e% A# R& i
  59.                 else' G* [5 u, T# f2 U; L2 H
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新- n0 H4 d( O6 q& ^5 v0 x' a1 }
  61.                         CONNECT_POOL[user] = socket;' r* G7 `+ @! q! J1 e
  62.                 #endregion+ P, l# r7 U; F

  63. ) \8 W  ]7 t6 X* I: p" f' L8 g! Z
  64.                 #region 离线消息处理- k* s$ T+ {+ s7 U5 F- q+ ]0 l0 ]7 U* U
  65.                 if (MESSAGE_POOL.ContainsKey(user))/ @1 W2 |" H* t" L) _+ L' n
  66.                 {
    & G' W2 \" k7 L6 I3 t
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];# }8 [' B( F# _) K
  68.                     foreach (MessageInfo item in msgs)
    ) d' g& E$ P& c) _8 {+ c
  69.                     {
    ! }7 |; ]  s- V3 k2 w7 g" ^" m9 N
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);1 f9 R6 W% y6 }7 t
  71.                     }" D" U$ c6 L% M0 d0 q% Z
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息* Q3 i/ c" ~' v$ Z& _1 W. }7 ^
  73.                 }
    0 e0 c  A  N2 g
  74.                 #endregion# r+ _- }! G1 f  y0 j2 g/ C. _, v

  75. $ H5 Z/ M. F* a) s7 O
  76.                 string descUser = string.Empty;//目的用户# f) ]. @0 ]  ~$ i8 g
  77.                 while (true)
    - H: C  C8 E' \, L
  78.                 {
    ; T; A" }0 t! Y
  79.                     if (socket.State == WebSocketState.Open)2 H% P0 {# D; ~8 n$ z5 H2 ^
  80.                     {
    + L, a/ n$ Z4 j' U* f
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    / z2 ?; F3 R2 R& A. n/ w
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    ; [9 j, Y* {/ y3 }( Z: n. h6 r9 ]
  83. * u# `1 t, Q# U7 n  \: d
  84.                         #region 消息处理(字符截取、消息转发)" Y; d  B/ S) B- Y5 ]
  85.                         try  {3 a. k8 r: T) Q1 X: j* R
  86.                         {
    : ^3 I- y( y& ?% ?* l) x6 O4 w
  87.                             #region 关闭Socket处理,删除连接池
    5 e% o$ y( a% \- i& Z# h
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    & `8 q5 f& ?5 C# a( _
  89.                             {
    / r7 k/ ?6 F" ^- n, l
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池# Z' J" P. X0 @5 ~+ i
  91.                                 break;, g3 v* z0 @  o: I. c  P
  92.                             }
    $ @9 C/ V! k* C0 w- B
  93.                             #endregion
    2 D+ O8 Q& l' I: Q* T/ u$ R/ v
  94. : l. A( s! a7 C" W" s* m! I3 e
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    " Q, K0 y5 D$ e! i/ h2 |# p$ e  j
  96.                             string[] msgList = userMsg.Split('|');) N! C4 |* J) \0 K7 A4 M* S
  97.                             if (msgList.Length == 2)- I+ C9 p: S6 \# G; k7 @: u
  98.                             {9 s3 [5 ~0 ^- F
  99.                                 if (msgList[0].Trim().Length > 0)
    8 x! {6 O% ^; o
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    ! `2 s0 q% u. S1 P, M
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    " c8 `1 @1 r# [9 C) r+ {9 v
  102.                             }
    6 A) M* t; _; l/ Z6 j$ C
  103.                             else: b. g0 Y2 G, D5 V0 i" V
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));4 f+ _& J7 {1 E' \6 Q8 f
  105. 6 p+ Z( d8 Q7 t- E4 ^" L$ `5 C$ V
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    2 c- D* t) s% k) K8 V
  107.                             {
    7 t  c1 E1 o7 v4 a4 P
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端4 t% S3 E& r( Z& L) }/ Q- J
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)) N: J; X/ `; C2 W
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);7 F) M% o2 ?9 e1 Q  s4 }+ Z& f! _
  111.                             }) l& v. }3 B' x# h: R
  112.                             else
    6 e* q" C; T5 g
  113.                             {
    ' s' _$ R- ]' J
  114.                                 Task.Run(() =>2 l+ n! O  v' k
  115.                                 {2 v: k( q% _+ K% M
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    ( Y7 O; q9 C' w" _* {
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());1 e4 \8 X: E0 [
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    4 f- k$ S, K5 I! k+ ]
  119.                                 });& }( {4 Y9 `0 T  [4 H2 w
  120.                             }
    ' I) |0 O# U4 N  r3 Z7 Q* v$ {! E! o
  121.                         }
    5 [' D. _' K: b# `' {
  122.                         catch (Exception exs)
    * O) X; x' b) @' b
  123.                         {9 [% O0 y: k5 c) N3 [* p
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息# _: Y3 x+ ~7 G' M& P+ H$ B) `
  125.                         }
    3 w3 J/ n3 d7 y! V* |8 s. \3 |
  126.                         #endregion
    & T" ^  s. c; P# w+ a, {# E
  127.                     }
    1 P  _; b( d  n6 }
  128.                     else
    ; S" R& W6 `) A) k- p! f
  129.                     {6 u  k. y9 G5 t& x
  130.                         break;0 S: ^' Q! c/ Q$ S& c$ C% w
  131.                     }0 h5 L' v2 O5 |5 }0 G* o) Q
  132.                 }//while end9 t6 H, D5 s& ?- {, c
  133.             }$ e' c  O4 q# L  C$ z6 _2 W
  134.             catch (Exception ex)
    5 [6 j) r- @1 i7 a. B8 P/ p
  135.             {
    9 E( v# z9 [4 K; T- S
  136.                 //整体异常处理
    ! J7 Y# d; c: h  ^- @+ U& g+ ]
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);, |; W$ u! g0 P9 S
  138.             }# r2 Z) z" j2 j) T
  139.         }+ K  g" H; p& `. P
  140. # s- W& i0 D4 X: B3 A  Q# F

  141. ( o4 r! r' b4 ~
  142.         public bool IsReusable, `% Z/ s6 F6 ?* Y, j' B1 M( b# a
  143.         {
    / ?  E  C) P; ~. Q
  144.             get0 n) g) B5 q/ B9 j+ m9 W8 C
  145.             {
    # f) k! \) J1 r
  146.                 return false;4 q9 k0 |( m5 u# `2 D: s
  147.             }' f/ O: ^& T& c- `1 w% H' E
  148.         }
    # \; a* f" K& a+ @  q, K
  149.     }
    $ I% P$ w; O% _3 B
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

  \7 o: v/ E3 z/ i) L& @: R( w4 `
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-18 23:29 , Processed in 0.114806 second(s), 22 queries .

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