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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |正序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
9 \5 E; g' @6 [$ b% x& s* v; ?% b
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;# y+ B! \& \7 C" @
  2. using System.Collections.Generic;
      m! R8 ~* c& E! l. [& ]$ u/ d; O
  3. using System.Linq;9 Z0 P2 l6 @! U1 j/ D/ M( v/ n7 D
  4. using System.Net.WebSockets;  ^; y: a% C: V  u/ z" `6 O
  5. using System.Text;
    & R2 K( K/ i6 }* e/ @
  6. using System.Threading;, E2 a+ Y2 ~  P
  7. using System.Threading.Tasks;/ Z/ s5 [' D' _( \
  8. using System.Web;
    ' L3 a" S$ z/ D$ b6 ~
  9. using System.Web.WebSockets;5 F& Z0 P( x- P1 x* f5 f+ m! }
  10. & N# [/ D" |* z: l( M) W! D

  11. ) Z; z) U9 W3 B- @3 M7 V
  12. namespace WebApplicationWebsocketHandler
    : ]: h5 ]6 k6 [: Z! A' Q5 S2 E
  13. {
    , h2 Y$ s' y/ D3 v
  14.     /// <summary>
    . w/ e( Z, ?7 m+ d: [0 {; O( A+ K4 N
  15.     /// 离线消息$ I- Z/ u6 f2 @" n( m0 A6 i, l
  16.     /// </summary>
    4 c8 A, V2 w7 ~: ?$ I& d. y
  17.     public class MessageInfo  G: |  U# ^3 u  \1 L" ~
  18.     {
    9 Q5 I, q, B4 R  R% I$ i/ y: m
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    1 p! y: F' B$ a0 x9 I; S
  20.         {! w% N' p  S* H# x& L
  21.             MsgTime = _MsgTime;7 L. f1 f# ^. B8 u( t# S7 F# A1 u
  22.             MsgContent = _MsgContent;; `8 Z2 P  _3 G  `! r$ i0 s
  23.         }
    , g1 x. `: c# o2 H
  24.         public DateTime MsgTime { get; set; }& Q+ E4 Y4 Y) o; y( ]
  25.         public ArraySegment<byte> MsgContent { get; set; }3 U3 t0 O: [1 F- q' K+ v, s
  26.     }- z* b* D* p6 @* o/ [
  27. ( o* A  g0 `+ t! r% J! W2 ~
  28. / e) M9 w3 M+ L

  29. 7 X8 W4 |5 J. }2 t- L$ H- S

  30. $ {; @* I+ e* D9 M! M/ @! b; {' x
  31.     /// <summary>
    % Q1 f, |! Y; G( Q' Z  M1 C6 y
  32.     /// Handler1 的摘要说明
    . ], a! W, l! p8 p" s
  33.     /// </summary>
    2 m" h" q6 G  ~0 e$ W6 a' U
  34.     public class Handler1 : IHttpHandler4 }! E$ f! @. [
  35.     {
    ) i3 Q# b4 E8 ^# j, ?6 ^, Q
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    1 _  g5 O! U& `$ ?
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池( Y5 N3 N# L- A5 O, z
  38.         public void ProcessRequest(HttpContext context)
    . Y) x5 Y* V+ p  T2 Y
  39.         {* F0 c+ Z6 H+ f% Z
  40.             //context.Response.ContentType = "text/plain";0 p/ O6 C! z: e$ D& z* `
  41.             //context.Response.Write("Hello World");- ?! p, I: P. `0 D; _6 g7 {
  42.             if (context.IsWebSocketRequest). n3 f' [0 N6 X# X2 T1 f2 D
  43.             {4 Y* m' y0 Z" g6 k: [' g
  44.                 context.AcceptWebSocketRequest(ProcessChat);# D. C' c0 p; L5 x$ L; y# N
  45.             } : X8 \: n$ |4 |5 x2 o5 e8 W  r
  46.         }7 I% M: @; P  T# L5 P6 _4 g

  47. ( M& \, q( v5 ]0 D
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    + n" O* I% ]( Z; `: v* \$ c: d% S
  49.         {) M, {( ]8 k- C( c9 b
  50.             WebSocket socket = context.WebSocket;0 h1 d9 C  w" |& P4 A; E& }
  51.             string user = context.QueryString["user"].ToString();
    ; t) f, w, c3 i8 m) s% F2 i
  52. " N- q  a9 d$ N  d& i6 o' u% Q
  53.             try
    8 i/ v8 D; [, Q$ J; |
  54.             {& I- ^* T" V) L. z0 H6 J
  55.                 #region 用户添加连接池
    7 K1 ~! n  Y! Y3 |* j- @/ |
  56.                 //第一次open时,添加到连接池中
    $ u* @) ?% o; e2 Z) ?
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    0 b. l+ E$ d( _
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加- ]- N6 f" O+ \/ J! n
  59.                 else
    4 h: c' H: |1 d$ B
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    4 p: }% R$ j4 u
  61.                         CONNECT_POOL[user] = socket;
    0 W' v) L& `* ~# b; |- V# i
  62.                 #endregion
    ( z6 s2 l. L( L  S9 z
  63. . W" P* P, y( Y0 Q2 q
  64.                 #region 离线消息处理
    + I/ Z: U! Z* Q, b7 ~1 r
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    0 ~2 s- L5 C  l1 P/ h
  66.                 {
    * Y% {" H/ K! M0 ]& j5 {6 Z- b
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
      ?$ B! T; [7 X$ t
  68.                     foreach (MessageInfo item in msgs)
    " R: g0 A7 ]1 Y5 X5 Q' Q
  69.                     {
    ' d! U. F1 r0 F8 g
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);! c9 P0 }# {9 X. c' a# i& `, C
  71.                     }
    9 ^0 X* s$ B" Z) ^. s
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息) O5 R: {0 v  ^- |( ^, y7 J
  73.                 }7 m5 {* c% B0 v7 m
  74.                 #endregion
    2 O* V9 E, r/ Q0 z& R7 J

  75. % }  c3 U, A* `& I
  76.                 string descUser = string.Empty;//目的用户; f. D/ y$ j+ s0 m3 p6 a
  77.                 while (true)
    ' D3 s/ r1 |, y  v2 J
  78.                 {7 N) x2 |" d2 G
  79.                     if (socket.State == WebSocketState.Open)
    1 Q! V( s$ ?5 {: a* H" a0 h
  80.                     {
    8 c: x) b" R$ Q) k, d! `. i8 S: e
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    ; z9 w- u* @8 s0 D
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    " z, I1 y8 t6 C3 @
  83. " _& ^% n- o! M
  84.                         #region 消息处理(字符截取、消息转发)) l# V8 r# S- K( C1 c! [
  85.                         try
    ; G8 |0 B, L. C# k) o' {
  86.                         {+ g0 l. m- J9 ]; P
  87.                             #region 关闭Socket处理,删除连接池
    4 ?; n  f  h# j" q9 U* t7 ^  Z
  88.                             if (socket.State != WebSocketState.Open)//连接关闭; F$ a, v2 s  e$ y) w1 s0 m
  89.                             {" [6 g: A, M4 E- y  a
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池6 ~( j) F6 c! ]2 G4 U) E0 F
  91.                                 break;
    ' V9 T; _3 C) E9 K' P
  92.                             }
    ' V" t4 a# P7 c2 ~+ ]  Q
  93.                             #endregion1 ]3 B7 q  G, z( r; @0 E

  94. " e. D, H7 G& ~
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息: U$ K. V2 Z2 E( m4 j
  96.                             string[] msgList = userMsg.Split('|');- _% k& C( H: b
  97.                             if (msgList.Length == 2)4 h2 S3 F% [+ |) J
  98.                             {+ Z: u+ v' o+ N2 f
  99.                                 if (msgList[0].Trim().Length > 0)5 z% L+ r; h5 M  o! E! A
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户3 g* o+ [- x# T4 x
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));+ U* A+ D. D2 \" b0 W
  102.                             }* ]1 j8 W/ N% y2 m
  103.                             else% T, _) A6 F) k8 G" N  s9 C+ n
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    3 `9 n# u" I" X% _) ^

  105. ! C/ v$ `7 H" D- v9 n
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    $ w  r2 A$ p; D9 _
  107.                             {! h1 p! W: ~- g5 m: t
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端: y2 Y' K4 D8 t, I
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    ' f, p, Y) |+ h
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    . Y8 B* ]1 Y# F/ _& e. `+ h& k- T( W2 g
  111.                             }
    9 N+ s& @. d" ?; V/ |2 {
  112.                             else9 }6 w, H' C, y6 H  ?
  113.                             {  S: _4 D. S3 z& X7 i8 D( S
  114.                                 Task.Run(() =>; O/ R, ~+ ~* s) q& Z
  115.                                 {
    7 [$ \* ^& R: y: u
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    2 U1 l2 g5 y7 {# |1 m, k/ Q* X
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());5 n1 P# p  }+ \8 U1 }
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    ! H& ~4 U  n. d4 d: D* X
  119.                                 });0 Y) N" r0 |8 ]# A! A% e
  120.                             }# `0 Y! G; l( t+ j$ {  `
  121.                         }8 W( H* K- T/ q8 c/ u0 T( c# r% K
  122.                         catch (Exception exs)
    ' s) e7 P# u& ]5 n. Y& R, I
  123.                         {( J) i  q# m2 p5 C2 Z. t% s8 C. q
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    * Y- h+ |5 |. T3 Y: z0 ~- ^1 R- O
  125.                         }! ~# v; @4 F; k6 X9 r4 u& J
  126.                         #endregion
    ! r" E4 r& k& `9 R- @; k( v$ D9 \
  127.                     }
    1 a, l1 N# f0 U  M" C% m+ u, G/ p/ e* l
  128.                     else6 b% ^5 M0 q# U/ w
  129.                     {% \# c% x# W2 u1 m: n7 u9 j
  130.                         break;( ^- M" X  h* a8 v( i
  131.                     }
    % K  b% b( x& x4 S
  132.                 }//while end
    ) D; b' J7 \7 m
  133.             }
    - y0 u! E( z7 Q) p, W& e
  134.             catch (Exception ex)$ a! M$ H/ ?: ~6 v& A6 p, ]
  135.             {) v. @; _% H2 e7 B: l: ^( N$ x6 ~- Y
  136.                 //整体异常处理  \: M" J6 L0 Y1 s) Y
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);' a6 l) ~3 [, q7 q
  138.             }
    % E% U) }) T- h8 X8 v
  139.         }
    . X4 Y+ c8 ^- |* [" _, `  }

  140.   o9 E/ N2 S+ h+ p" `
  141. % }7 i( `9 h7 z% w
  142.         public bool IsReusable
    . z8 f1 Z3 H# \
  143.         {9 |# N( L- H! a. c* F( \
  144.             get1 m+ y9 r( r/ B! d! d# m
  145.             {- c; J: {7 `& o! W8 O
  146.                 return false;
    - g3 ?  a: H/ n5 v
  147.             }4 G% ~4 u! {2 L& I' l/ n0 B2 a: `
  148.         }
    ! f4 A; u& `6 X: Q# G. Y' N
  149.     }' N* P8 ?" I, H  o
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

. Z4 n- _. \, T# A
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-8-4 11:46 , Processed in 0.056921 second(s), 23 queries .

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