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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
/ c/ S. C" @) r2 y3 V6 t+ Z0 k
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    / I% I: c8 c* S) p+ A9 h
  2. using System.Collections.Generic;
    % P$ |1 @$ [) f  s+ P
  3. using System.Linq;
    6 ~% e/ L; W% w/ b+ v1 p( t9 _* e
  4. using System.Net.WebSockets;
      G* i' J9 q( a% p+ ]# P! S
  5. using System.Text;
    1 d' r3 y) V6 e: N0 j( q
  6. using System.Threading;" V+ n! F5 t! G8 Q" X
  7. using System.Threading.Tasks;
    - L9 B; P) `) l5 Y- \
  8. using System.Web;. u& F: o' \5 ^
  9. using System.Web.WebSockets;1 O* R( U- l/ e6 h
  10. 8 d  {7 T! O3 S0 C2 q
  11. ( ?6 o. R: z+ Z3 J
  12. namespace WebApplicationWebsocketHandler
    ( S# R& y$ k- j3 U( ^% F
  13. {
      o; H* z; D& y  T3 r. H
  14.     /// <summary>
    0 l* O8 [2 r* C" L
  15.     /// 离线消息6 ^$ r2 c  P4 N  c
  16.     /// </summary>! L! A% ~& _5 W
  17.     public class MessageInfo
    8 J. j9 E, s2 A
  18.     {- P, v# v+ z( h: q' R( _
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    ! ^! a! S$ d0 w% S3 ~# ^
  20.         {: R' j! O( h+ I( G& A
  21.             MsgTime = _MsgTime;, V& j& k- M* V/ U/ Q6 I; l
  22.             MsgContent = _MsgContent;  h5 C4 m7 d/ R* P! x8 m
  23.         }
    & z7 |  l, \5 T
  24.         public DateTime MsgTime { get; set; }7 R3 N2 w* O9 {0 q. B
  25.         public ArraySegment<byte> MsgContent { get; set; }
    + ^3 o0 r4 b9 @
  26.     }3 s7 Z1 ^& j9 F& T5 l$ V

  27. ! X; t2 b: I& G1 f" X; [0 z" d
  28. / W# x9 t2 i3 Q" g
  29. ! x/ G  H0 [; f( b7 I

  30. ! {- k% \$ s* {3 @% y" R4 Z) F
  31.     /// <summary>) a* O, H+ ~* {; J& B+ [
  32.     /// Handler1 的摘要说明
    ) s, @0 C2 ?5 j9 x$ J  u1 f
  33.     /// </summary>. _9 a5 O  i* @4 F
  34.     public class Handler1 : IHttpHandler) ^2 a& Y7 S2 C3 M
  35.     {
    2 \  N/ @9 E; z: A  D. k- _# K* m6 _
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池, R9 V# a/ R7 M# `7 j8 y% ]+ G: ~
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    6 ]( U0 e7 o' f& M8 m! w1 s2 F7 B  t
  38.         public void ProcessRequest(HttpContext context), ]6 x- G0 L1 p
  39.         {
    / h" S0 ~2 z  s6 m' _
  40.             //context.Response.ContentType = "text/plain";' V3 b9 F  l* P
  41.             //context.Response.Write("Hello World");5 q( C' V- N. L: y3 G* y: [
  42.             if (context.IsWebSocketRequest)
    0 g5 m* E# m$ w% S9 k! Q$ P
  43.             {0 v- Y- H5 L6 P6 {
  44.                 context.AcceptWebSocketRequest(ProcessChat);: b2 f7 |5 s4 R* n0 d" _
  45.             }
    * j$ c( C: V% O8 l! A4 t
  46.         }
      _% J4 [: ^1 A

  47. 6 f8 s* o0 m3 ]! ^8 I5 x: n
  48.         private async Task ProcessChat(AspNetWebSocketContext context)$ P5 Q. m* p% t+ B! ?+ I8 P
  49.         {! o! [6 M  X' \4 y  e* y6 ~
  50.             WebSocket socket = context.WebSocket;
    * r5 k/ r4 e6 Z; t
  51.             string user = context.QueryString["user"].ToString();
    * W" V1 R' G. }8 V2 M4 k# O

  52. , ?6 e$ q) E" r  f- a4 w& P' `
  53.             try; J. @8 O  q! j
  54.             {, E* ]' Z0 d% I  ~3 e% S
  55.                 #region 用户添加连接池
    : M# M6 `9 W: y
  56.                 //第一次open时,添加到连接池中
    ( ?" v  R# i9 p5 Y# n8 f( h" k
  57.                 if (!CONNECT_POOL.ContainsKey(user))
      M8 x8 b( y0 l
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加( p) M: y2 F2 s" v
  59.                 else
    ( d) q3 v& b7 l% h  }$ k
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新! f9 u% e8 ~* C& v: V" K) w
  61.                         CONNECT_POOL[user] = socket;# w; _% m. `& ~1 `
  62.                 #endregion
    ! H- @" ?* ?' b

  63. , ~, E) ~. v8 o; j. N
  64.                 #region 离线消息处理
    8 u: f8 j4 [$ H- W
  65.                 if (MESSAGE_POOL.ContainsKey(user))% S% c/ }/ b5 A) I' K% J9 p" i
  66.                 {
    / P+ |& ~- {8 o" x
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
      s' F& D# c( G- \: Y5 t7 Z4 M
  68.                     foreach (MessageInfo item in msgs)
    % ?& j0 J/ o: `! e/ h0 f% a( n
  69.                     {
    $ t0 x  z/ f  ^& L- j2 j
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    - O8 ~9 n6 S, S4 P, J4 @
  71.                     }$ u2 o4 ~! z5 U4 R- ^
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息6 @2 r$ c! i4 W; C, F1 D
  73.                 }1 s% D- W0 x  T( t
  74.                 #endregion% T5 h( u" J3 d% ^1 E4 p
  75. 7 A5 {8 W( n& K' w5 W
  76.                 string descUser = string.Empty;//目的用户
    % O  e- B5 A6 u# T2 b8 f* k; f! E
  77.                 while (true)
    * N; p' M3 h( s2 }. d2 U
  78.                 {2 R" L1 E' k3 F+ D4 u
  79.                     if (socket.State == WebSocketState.Open); @$ H( F. [5 }; b
  80.                     {
    / }! U0 C/ J$ b* Q  ]+ t
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);5 d3 E$ c) p: q& B
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);8 u) @! W( q- U
  83. " p8 v$ t5 _7 t7 u  k# x
  84.                         #region 消息处理(字符截取、消息转发)
    7 [$ }$ I) I* p1 c5 ~& V3 A
  85.                         try9 b" E  o; C( \, J# ^9 k4 x( t
  86.                         {  P9 z8 |- g8 m3 a, d# M- P
  87.                             #region 关闭Socket处理,删除连接池
    * s) J' Z. t8 `8 P: E6 ]3 `
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    4 Z. V- R8 V; d$ P1 Z" a  R/ v( e
  89.                             {9 M7 l2 a: ^6 ?, f
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池8 Y$ M0 P& W4 \7 w! n% r" z% r$ |
  91.                                 break;! t' M/ h2 a% T/ p6 {- ?) B
  92.                             }9 H5 n+ T+ q5 v( o/ N& X: _+ ^
  93.                             #endregion
    " Z! w* N  {; r" [+ D

  94. # X2 l& d! G# \/ k: o; Q9 g* C5 C
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    - q9 M1 Y4 b6 y9 a5 j* v
  96.                             string[] msgList = userMsg.Split('|');
    8 H3 W) v& d; {/ f' y6 D
  97.                             if (msgList.Length == 2)& ?% u8 P# g' ^$ X  Y# Z- u
  98.                             {
    $ q& j8 l' l$ K: H) X9 N7 D2 {
  99.                                 if (msgList[0].Trim().Length > 0)
    " \- j- i, l4 k( \) K- s
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    : {* r. i* L5 o0 [
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));0 i. C( s( _3 ^" j% @9 j0 S: |6 |. v
  102.                             }
    : B( N5 ~5 |& o5 Z
  103.                             else+ b9 x. K8 E- `1 z. ^
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    % R- K! j6 w9 x# w1 _$ f1 u& x
  105. ( |3 U" c6 ~6 |% J: l% c1 R
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线2 I9 ~  h4 T, }. C! C  ?+ O# Z) {
  107.                             {5 D2 F- I: L9 `: q) E  Y  L
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    6 t# h7 ^  h( x$ ]5 w. x
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    4 D0 }0 w! z+ J7 `
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    ( Z- t+ c9 T; ^( q9 {
  111.                             }
    * y  m% y8 g( w' p9 I' n' ^8 S
  112.                             else
    * H) U" M+ b, X
  113.                             {
    0 d) {$ D" V$ y) `5 q% |* n) w
  114.                                 Task.Run(() =>
    * y' s" O' g4 F, ]
  115.                                 {
    # R2 j/ }' O. P. T' x
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中- e1 q, Q* |" m3 A. E3 }7 b0 |
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    * c& u' F% }9 i" O5 d& y
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息# r6 s# R3 G: r1 W0 j( e' ^% F. f
  119.                                 });# d6 n, ]+ c, q3 D9 X* X
  120.                             }4 c( k/ f* `; u# S" Q8 H& q" ~+ [
  121.                         }1 f1 s  E. R8 v. V7 Q- M) x, S9 o
  122.                         catch (Exception exs)
    * _% H* i8 ~2 N
  123.                         {' {3 j$ f) a( q# Q* j
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息9 v" N+ Z2 ~  g6 @( ?4 z. L
  125.                         }9 J/ e# d+ V! z4 F
  126.                         #endregion
    1 ?" C1 _9 W3 q& y4 a1 D; Q! _
  127.                     }
    3 L9 R2 ]0 J) q5 C) |8 T2 f
  128.                     else% i8 F- e" i" T5 Z' c2 z) i+ z$ q4 \5 D3 s
  129.                     {
    1 D2 _  W/ i! B0 R, \) C4 w* r6 f
  130.                         break;
    " m# o% }7 ~) X* K8 ^
  131.                     }
    ' j) u' @3 }1 d
  132.                 }//while end" ^( S! J* _/ d3 M% o7 H, U5 l
  133.             }' M8 G* E2 t7 `1 R" P. c
  134.             catch (Exception ex)0 E1 B$ i! F) J3 D% S3 D, ^! o! [
  135.             {
    2 w# l& U, _+ P  C# R- s
  136.                 //整体异常处理
    7 u; ~6 E: H6 q/ t3 w! u
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    0 v( I/ o" _4 n6 e
  138.             }
    + h+ [; b# f6 K8 h7 \
  139.         }* q, m: L6 G6 n+ R

  140. - W- o3 X. z) Z8 d4 b

  141. ) w8 A( o& [% M- ^3 N" u( G
  142.         public bool IsReusable, v* t. r8 i4 y. N6 W: |
  143.         {
    0 @' S5 N# X6 `2 T3 s. y
  144.             get. Z5 f8 G0 s. U& y; b" h. @% c5 W
  145.             {
    # ^# H* J4 g2 h7 @4 ], v- o+ N
  146.                 return false;
    ! P. U% C' F# y; T1 ^
  147.             }& V* s2 Z' ^: ~3 _
  148.         }$ s; `0 F  @2 B8 g) T1 a& a
  149.     }' {/ P+ _1 s4 V/ ~3 e
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

! I* ]0 h% S" _8 _4 O
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-8-4 12:39 , Processed in 0.053362 second(s), 22 queries .

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