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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

: Q/ f' H1 ]4 I2 W
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    / w: s( D; N: D& `% H. z
  2. using System.Collections.Generic;9 L0 x# R% X" P2 V6 O
  3. using System.Linq;
    6 f) Y( y" z, q3 w# q
  4. using System.Net.WebSockets;& G# [. s% {- i9 D7 P; U/ J
  5. using System.Text;
    # C7 r" Q! m, E8 p! i+ j, I
  6. using System.Threading;
    ' Z. o0 g/ I/ E4 D& \
  7. using System.Threading.Tasks;$ @; F9 W* m% Q) u
  8. using System.Web;1 A/ N, G* T( _5 A+ F, r3 P% z  i
  9. using System.Web.WebSockets;8 P% J  d: k) t0 e9 G

  10. $ ]* u$ \/ t9 `1 \8 u3 W" I
  11. & S' p  P, F4 v
  12. namespace WebApplicationWebsocketHandler
      X9 ]; Q: e8 Q0 t( S8 D! r/ Z5 ~& `
  13. {7 G1 d4 Z/ Y5 j5 n
  14.     /// <summary>
    * M$ a. W  O: K% c: |! F) [$ f( D% P
  15.     /// 离线消息5 U, u. Y+ A% J* {
  16.     /// </summary>
    7 T1 x6 s$ g# z: H! r" w+ m
  17.     public class MessageInfo
    ; z5 W2 y  t! g  e4 U1 ~5 {
  18.     {
    * P: m+ |' q' u6 O- }* W) \. \
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    $ o5 b  a# c7 G% J/ \
  20.         {2 a% f! I# i- u- a
  21.             MsgTime = _MsgTime;
    : J$ |; B" l: K6 [$ G$ W4 k9 C
  22.             MsgContent = _MsgContent;& F. y7 D, ^4 F
  23.         }$ U  {% Z) C( n/ {, Z
  24.         public DateTime MsgTime { get; set; }
    5 U( Z3 [5 G5 J6 b
  25.         public ArraySegment<byte> MsgContent { get; set; }; u- Z0 m3 A' M8 t
  26.     }
    , \0 k& T/ b& U) v! s
  27. ; r, u& w9 {0 v  U

  28. 5 U/ E$ s3 ~  l* Z1 U% R

  29. 0 I- u* C( O& K

  30. 0 d! J2 h4 v, P0 F( I2 {
  31.     /// <summary>9 Q. d; q+ ^5 l
  32.     /// Handler1 的摘要说明
    4 h3 h! y5 v& {3 T$ |5 M0 x- Q! ~
  33.     /// </summary>! }6 i3 s( }( O, h0 g0 y& o( x
  34.     public class Handler1 : IHttpHandler, G0 ~" F; ~) l5 g0 |
  35.     {) P7 ~9 D) k1 q3 r: P: w
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    5 Z9 e1 e4 A: G1 \- R
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    - Q: u& R4 L; ~- O5 @5 Y
  38.         public void ProcessRequest(HttpContext context)7 S2 L5 ]5 x4 J! c
  39.         {  h5 {: S1 B. Z  T  K
  40.             //context.Response.ContentType = "text/plain";, Y% ~" q: Q: S" C5 U% e
  41.             //context.Response.Write("Hello World");3 g' J! X: h* k$ c7 k
  42.             if (context.IsWebSocketRequest)' q& l* E- O/ o4 I8 M) ~4 [1 g1 Q
  43.             {
    ( D; c* {3 A% t0 _7 H2 l+ f- |
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    / c. L+ t5 P$ Y8 ?
  45.             } : W# j; n. r9 f
  46.         }
    ( H  C9 o  u- Z& [1 v5 ]

  47. 4 o9 Q8 d# h/ e
  48.         private async Task ProcessChat(AspNetWebSocketContext context)9 t) y& N/ {) U7 u! w& `% f
  49.         {
    : c9 C1 E- m) j; ?- X$ E" H- n# E
  50.             WebSocket socket = context.WebSocket;* F" d" I3 b0 M  [/ v
  51.             string user = context.QueryString["user"].ToString();
    * I2 P6 [1 Y1 ]. Z0 ?+ d, u4 c. j
  52. 9 b' p# d1 s0 C* W2 {! \6 {) B
  53.             try0 m& H# |0 Q* u# F
  54.             {0 x- {8 u* o6 P
  55.                 #region 用户添加连接池
    8 D! R' s) A- x  ^- h4 T
  56.                 //第一次open时,添加到连接池中
    * P% @, N# v1 f! @  d( x( @# Y$ L" P
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    7 l( R  o- @2 n  J2 R
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加1 q7 s3 E5 T. R) d
  59.                 else
    6 F- [3 `" R  L* ~3 Q$ L' f
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    2 T* z; t2 g- r$ Z! i1 G) Y: g
  61.                         CONNECT_POOL[user] = socket;
    / `% C  O0 E( Z2 B8 h% a$ G  i, z
  62.                 #endregion9 U/ G$ j1 g) [7 R* C. o) C! V5 v4 y

  63. - Y) F) [: _' {6 _. d! s
  64.                 #region 离线消息处理
    % ]$ m2 D; C% x/ D. Y) z
  65.                 if (MESSAGE_POOL.ContainsKey(user))0 Y  {( W4 A/ \6 _! [5 Q( K
  66.                 {
      D1 E+ p/ @6 B4 ^
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];7 Q& e+ U. i8 T5 f
  68.                     foreach (MessageInfo item in msgs)- S3 x6 G9 y7 l5 `- U
  69.                     {' T  P+ I' b# e
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);$ O& g7 Z' l) s8 L/ g) ~
  71.                     }/ K7 R( @3 X$ d4 u' W. C) x& d
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    ( b1 {! ?. Z5 U/ d& S7 k- b
  73.                 }- q% e0 Z! O: e1 p: E
  74.                 #endregion: [7 ]- \/ L3 r2 J/ ]
  75. - M* @$ r2 o3 H5 Z
  76.                 string descUser = string.Empty;//目的用户% g0 N! N/ C) c8 Y: I, [
  77.                 while (true)
    3 D+ c4 n2 f& o6 \
  78.                 {. ]; a$ h$ Z# y2 B  @
  79.                     if (socket.State == WebSocketState.Open), F" j; g+ F& {
  80.                     {0 n: [7 s3 s1 r7 g: ?' u
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);1 Y; Y7 B/ `+ f5 }# _' t/ g' T+ Q* R$ N
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    # v6 J- O  Z& d

  83. 2 [" ]( k4 w0 n+ I9 d3 C
  84.                         #region 消息处理(字符截取、消息转发)+ A" P3 _" N* s7 Y  x- `8 K
  85.                         try5 S+ n9 c1 e9 J! h
  86.                         {6 l5 `+ v5 A, ^
  87.                             #region 关闭Socket处理,删除连接池
    , F+ s; N* b& \( U
  88.                             if (socket.State != WebSocketState.Open)//连接关闭8 ?( F0 V( I3 F. O- m% H
  89.                             {
      \% D1 A6 W2 B9 k) U1 t
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    " D' c# v0 [. |/ _) [! x% C
  91.                                 break;3 x' q  H2 U" F$ l( Q
  92.                             }) ^6 u/ b3 J9 M. n; O
  93.                             #endregion
    & s4 b" G) f  L3 v( m

  94. + @/ z; H2 Y- ]3 l1 o: `: i( k
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    2 }% {; Q" j: |+ B2 Y7 V( j
  96.                             string[] msgList = userMsg.Split('|');
    # w- R7 M: o+ c* @0 A% t( v
  97.                             if (msgList.Length == 2)* Y4 \* U5 z, [6 [4 M: w5 v( A
  98.                             {
    + k$ H( v% A$ q) y" H
  99.                                 if (msgList[0].Trim().Length > 0)
    " X* n# L6 `0 `0 t  p+ h- L
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户; h! r: ]/ j$ m+ _$ C% F: {% X
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    + o) b3 b( S. n: c0 ^( q
  102.                             }' J3 T5 P8 }& k) L
  103.                             else* Q/ ], B; p; w8 }6 F. d3 N
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));% Z$ n" V/ Z1 S

  105. 4 i2 l) |0 ^2 F. S7 \
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线* D; b0 N, J% N2 l4 ?
  107.                             {) ]* A) I+ M& p+ H7 C
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端& {, ^. w4 |, \. o2 s0 h
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    & M: F2 J6 ]  D$ T# g+ R$ i, \% B
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);4 X8 p( Y  Z$ u
  111.                             }/ V' m2 Z# H6 G
  112.                             else
    5 V5 L9 t5 U5 `
  113.                             {
    * I3 R+ i5 B. S6 n8 h6 x
  114.                                 Task.Run(() =>
    5 E- [: H! I/ ?5 ~; s
  115.                                 {9 F( m0 p; V2 a. S* A1 r8 G
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    ! `) R- c" @3 q0 S/ r
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());0 \( _% M' s4 M2 y% z/ L9 w8 B
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息" t  v- U/ j  r7 z8 U5 G
  119.                                 });
    6 C# N; t1 M* `" J8 f0 d
  120.                             }1 r" Y6 T+ X. K& K. U; C
  121.                         }
    ( ~+ f$ b4 e& n, D, C- u6 k3 E( H! t
  122.                         catch (Exception exs)0 q. ~$ Q3 R% q7 v& v+ t
  123.                         {3 w/ G2 X* `" u. A! Z
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    . X% ?! |5 m) G2 V% r7 F
  125.                         }) x! B. N$ w. g' [" |  _
  126.                         #endregion
    + T  n4 }, G1 D( q$ |
  127.                     }, ?7 X5 w7 w! C  j4 B: E
  128.                     else% @1 c1 h6 n3 W
  129.                     {
    : l  Y  h3 b3 n$ q
  130.                         break;4 D0 @3 z1 }$ W
  131.                     }  o$ ~! ~1 ~& P) ]; c: r
  132.                 }//while end2 `% e- S/ t# S
  133.             }. l* k# F5 ^9 A- ?
  134.             catch (Exception ex)& w4 L% g4 S* Y8 X
  135.             {1 s+ u; g( x: c6 R* V' P' `. t
  136.                 //整体异常处理2 U8 C2 K& x0 Z+ b
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    ) ~( H4 y+ ?- O! e; z8 k0 ~
  138.             }
    2 s7 y9 n8 T$ Y3 X
  139.         }4 u9 h) J0 T' P0 [, G

  140. 4 ?' J. c3 |4 `  E: u0 }6 y

  141. ; I2 V8 j% i- M4 d5 L7 C
  142.         public bool IsReusable
    2 j7 x' e- L/ p4 L. k# Y* K
  143.         {
    - \3 Q3 i" c; ]9 x) I2 ~
  144.             get' g, C; g6 K6 A% V. A* ?
  145.             {
      F- T8 R% p- b. r" e
  146.                 return false;% g' Z/ h) m; r+ J; ~6 a; w  l$ C
  147.             }0 Q4 }' x# B8 i& h- R9 A$ y! }
  148.         }1 M- v+ v! w- E6 K1 P1 o& m! I( k
  149.     }# O0 n# C" K/ X4 p- H' i) l+ l
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

  f: w$ p& u6 O, Z# z
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-20 05:05 , Processed in 0.155047 second(s), 22 queries .

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