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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

. C* ?7 F- _" k7 L* u" ^
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;/ s* S; r* u" G5 W2 E
  2. using System.Collections.Generic;
      N0 }/ A" ~: N8 n+ N
  3. using System.Linq;
    8 |7 j- [$ k2 @$ K4 T
  4. using System.Net.WebSockets;
    0 S& `5 z4 t$ x/ `1 e& x
  5. using System.Text;% [2 f& L: K8 V7 |
  6. using System.Threading;
    ( J6 f: i3 h. T8 I, ^
  7. using System.Threading.Tasks;. [. g9 d" N$ @# X/ \  o% {
  8. using System.Web;
    ; b% l2 g9 [* u" v% h" U
  9. using System.Web.WebSockets;. Z( A6 W6 H9 h1 `$ }0 {

  10. 6 E/ ?4 i/ V' q# M  F# z# q: A0 @9 D
  11. 4 s' R0 |) Z3 ~& d: B
  12. namespace WebApplicationWebsocketHandler
      o. m0 T4 p/ Q7 Z8 F  _1 L3 t0 O2 t
  13. {
    ; C6 o! [3 _( ~5 }. h" G
  14.     /// <summary>
    + k0 _1 u- K* b2 @" Z0 m
  15.     /// 离线消息1 O9 \; e% ]* l1 _( n+ b
  16.     /// </summary>
    ( Y: x. ]+ G- h5 N
  17.     public class MessageInfo
    - y& y4 M% \! V% F7 l* x9 U2 Z
  18.     {
    " D3 k2 R+ u# q6 }
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    ) n5 Z& ^0 {0 ?- T  _& s( f  F7 L
  20.         {+ r2 d$ d* D# ]
  21.             MsgTime = _MsgTime;; x8 l" j7 x( {  S
  22.             MsgContent = _MsgContent;9 g, f4 S! a6 p# x& E1 l
  23.         }
    $ w2 ~' g: k& l8 v5 ?
  24.         public DateTime MsgTime { get; set; }* D; R! e* z- ~' o
  25.         public ArraySegment<byte> MsgContent { get; set; }& ]: [6 E# K! L3 ~
  26.     }
    $ K0 ^" x1 Z1 I5 u5 U! b" W7 ]
  27. 8 r1 Q* w2 B" W* I" x
  28. / ]) y! q/ K( _* u4 N! ]" a

  29. % ~# R- y5 H+ ?; p3 f
  30. ' ~2 t3 }5 E0 W4 C$ ~  @/ r
  31.     /// <summary>% Y( @  v) ?4 ?% U( k
  32.     /// Handler1 的摘要说明( J. x/ j* d( G+ ~. F- l1 ~- w: G1 b
  33.     /// </summary>
    6 |% n* Q2 F6 r- f
  34.     public class Handler1 : IHttpHandler
    , v4 f0 w) v7 v- G5 d# @& Y
  35.     {: h2 \9 e; f2 b' x6 X
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池; h, w; _' u3 Y! P; |* ~
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池$ s  t2 x* y1 Z
  38.         public void ProcessRequest(HttpContext context)
    ( L6 ]' r! z, u$ b! x( h# R
  39.         {
    ! x. Y7 x. H5 V8 P( ]' Y3 r! e
  40.             //context.Response.ContentType = "text/plain";
    7 C0 p/ V3 V  S8 i
  41.             //context.Response.Write("Hello World");
    - U# P3 E, |# [9 R  Y9 {4 i
  42.             if (context.IsWebSocketRequest)
    2 c3 _1 V# a- b) q
  43.             {
    ! a: W& ]5 H9 C, ?& }. y
  44.                 context.AcceptWebSocketRequest(ProcessChat);* p0 Y- J% [! K; ~  Q
  45.             }
    # T& Z+ X* @; `- X+ j% ~3 u
  46.         }% C, F- `8 P. \9 ^, ^/ M

  47. 9 A# d6 ]5 D' b0 @1 i4 v
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
      Y; U6 l+ Z" m3 ?
  49.         {: |# Q* s, S, m* [7 C5 f5 ]
  50.             WebSocket socket = context.WebSocket;! {% e& n  B( E1 H
  51.             string user = context.QueryString["user"].ToString();6 A0 i) i6 p) g$ z5 E4 J0 r# U% p% V

  52. , w9 N, J0 T5 p& r& F2 i. }  j
  53.             try
    ( I. v# e. f- x8 U* V" K  X. ^9 E
  54.             {# j/ U1 o! R% b* h. v
  55.                 #region 用户添加连接池
    8 \8 z& ^% O* O6 ~# J* M; p7 _
  56.                 //第一次open时,添加到连接池中) _, Y- ^$ U1 e8 E. R" ]  V
  57.                 if (!CONNECT_POOL.ContainsKey(user))% ^3 C% S- U" q% c
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
      M2 M. T7 K9 u
  59.                 else
    2 N0 Q, c& G  I/ J
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新5 @, \* o! j" U& m' K0 Y& s
  61.                         CONNECT_POOL[user] = socket;  C% P5 Y+ C/ }# @
  62.                 #endregion
    8 m8 R& I( u1 `
  63. ; k0 j( b' A; R3 P9 J
  64.                 #region 离线消息处理- G9 {2 ]) R* n/ {+ _
  65.                 if (MESSAGE_POOL.ContainsKey(user))  S4 l: O6 I- w3 {( \3 p* l
  66.                 {6 C3 R$ R( R0 u0 q! p
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];0 ~- A) N0 d& U1 I
  68.                     foreach (MessageInfo item in msgs)$ P0 d; d4 i0 b8 R' r4 h
  69.                     {( W; V3 \  x! o4 r# y
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    ( R9 V: ^+ y, n9 M
  71.                     }
    2 Y% l' ?" G1 A/ C4 y; }) h
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息* s! C3 h6 T. k# \) D/ o6 R4 [
  73.                 }
    7 T) K" K# ]: u  g; V2 T' C* N( f
  74.                 #endregion
      \! x, S8 L  B  y/ P3 h

  75. 5 ^8 [( \/ M* H. X4 E) M
  76.                 string descUser = string.Empty;//目的用户  P2 |& `6 Z$ ?4 J3 q
  77.                 while (true)- L7 Y0 q' T  A$ [, Z
  78.                 {9 X+ ]9 s7 |3 o
  79.                     if (socket.State == WebSocketState.Open)! r* e! B" z: h, |! d
  80.                     {! ~) `- J. Y. ^% h* X9 u  y' j
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);; F: A6 J" N0 b4 y
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);$ g7 I8 R) j6 @& J

  83. 9 v( ~* t8 j+ |2 ~1 m$ s
  84.                         #region 消息处理(字符截取、消息转发)) U: o5 v: n0 l8 I; D
  85.                         try
    : z. n1 V6 j0 ^# A1 o7 h7 T3 u
  86.                         {/ D* \4 j. @. J2 Q5 ^
  87.                             #region 关闭Socket处理,删除连接池
    + g2 C4 I) k0 ~; t) [$ o5 ?! A: u' ?3 q
  88.                             if (socket.State != WebSocketState.Open)//连接关闭& ]' T' [# b* h4 a1 g; P. f
  89.                             {
    & [8 l% S" K0 O" F0 }3 Y  I5 v
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池$ z" J5 c/ Z% A7 \1 ~
  91.                                 break;
    & q* E# ]1 f, s9 S# A0 M
  92.                             }
    * i( y: ~7 k$ x# ^1 q
  93.                             #endregion4 A. k- i/ H1 x& {' l+ \% j* U. [
  94. " v7 L5 f6 S' b9 X' o/ P1 I# L/ t4 S
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息+ Y$ H. n/ ?' X7 v
  96.                             string[] msgList = userMsg.Split('|');9 x- ]3 m; F8 \$ H" d7 L6 z
  97.                             if (msgList.Length == 2)4 s  `7 k( b3 A  h. Q
  98.                             {
    3 ^. h- j! q* l2 \# X2 k
  99.                                 if (msgList[0].Trim().Length > 0)
    # m; l3 E" n! [: I! Z( k
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    3 {8 J$ |* j* [& \9 Y, e, X) b
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    2 V$ r5 `% n; ]1 e2 c) V
  102.                             }
    7 }$ z, m% p, v: k
  103.                             else/ q9 \2 t% h' v: K  k: h
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));$ I2 d0 {; x" r& e  [7 i  i4 T% R

  105. $ ^+ X# w2 l' v$ Z* e: V4 N
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线7 A/ r. R3 o1 _+ R7 B- f0 ~- ~
  107.                             {  F" T" x8 t- U& K: N
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    . ]5 V# t  Q; n9 L7 y. L3 ?
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)  E2 [! M* E6 e# @
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);, r8 y# Y- o; m5 j! ~" T
  111.                             }
    $ f# h! z0 b# R7 i7 \$ c5 E+ F/ t
  112.                             else* L% D9 b% |, j$ t$ |; Z7 P9 z
  113.                             {0 C- L: m/ ^1 c5 g& K4 x
  114.                                 Task.Run(() =>/ m& e0 ~$ Z/ y/ S
  115.                                 {' E. O9 W8 D# V8 t6 b, ~9 G* W1 b
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中1 O1 W: y$ f% }6 B9 X
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    - J/ Z" x1 v) C
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
      ?1 Q1 T1 s9 a1 p. t/ x
  119.                                 });
    1 i, U. D7 b% _& _7 P
  120.                             }6 p1 C9 n/ G2 j* z; |1 r( [. G
  121.                         }0 T3 _% K; w1 t+ {
  122.                         catch (Exception exs)
    % r: N3 a  h, c5 V; F
  123.                         {
    ) G9 @9 v- G. _) j7 R6 E
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    ) ~2 L0 x* y% W4 V
  125.                         }. }! c  |! e4 ^8 A: K
  126.                         #endregion
    4 B' A! P' ]: x
  127.                     }( h+ K3 A  K! M2 u) ^/ X& l
  128.                     else  x- v/ u  f& K) @. o
  129.                     {5 N+ U/ ?# x! w$ h( o! ^
  130.                         break;
    + [$ l3 g3 w2 k
  131.                     }( Q& V1 I# ?. w0 Q
  132.                 }//while end
    : q) r$ }  `* F4 h6 u6 `' R2 M
  133.             }
    + U/ C" @3 ?9 f1 Y
  134.             catch (Exception ex)- H% L: J1 _  {' x
  135.             {" \7 S& t  s/ N2 S: `9 [
  136.                 //整体异常处理% F7 d! Q% Z3 v9 ~# W  @; I5 U, t4 q
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    : B: k1 g, U4 G! }8 k5 N. P6 m
  138.             }
    ) y! L# G4 }( }2 u/ S, X0 r
  139.         }
    7 x$ n6 f0 D6 @$ u- y+ Y

  140. 3 f) b% Q' }5 e. h6 o* u; J' s; |
  141. 5 E! `* N! r7 z6 W- w3 T
  142.         public bool IsReusable8 u4 P- F" N& Q& }
  143.         {2 ]: X6 g6 e" C4 m9 c7 e
  144.             get5 N5 z5 h  l- q% U. a0 `5 E5 X
  145.             {
    5 C: w1 j$ D* b- H4 _  P
  146.                 return false;
    ' P  d/ w9 C* [0 M
  147.             }1 z, D1 D! O/ n  f& ?! ~% b% [
  148.         }
    - y' B# m4 H3 [- s: V
  149.     }5 L! K8 S1 b9 y, V
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

$ O6 T* g- G$ M7 ?9 A! m
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-5-2 15:30 , Processed in 0.089470 second(s), 23 queries .

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