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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
& x4 M( r5 ^& `
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    : g2 D" n$ ^& J- m6 k
  2. using System.Collections.Generic;% S1 g8 w  t2 Y" l# F7 ^: F
  3. using System.Linq;
    4 D; r( |' B4 E- D
  4. using System.Net.WebSockets;
    7 A; e1 K! g+ @% `: k
  5. using System.Text;
    , l, J& Y: y: c
  6. using System.Threading;
    / j/ z, S& G# @* ]( {: ]: X- k
  7. using System.Threading.Tasks;+ W4 K1 a  Q7 S& }& y9 c
  8. using System.Web;5 |/ t, f; ?1 p6 B" s& h9 z- ^
  9. using System.Web.WebSockets;
    0 f$ I7 B% u: x$ o, {% K& h; h

  10. 6 c4 |4 G7 R; f
  11. ( H2 ?/ ~/ B+ u5 a
  12. namespace WebApplicationWebsocketHandler
    ( b* h, L) d, R
  13. {  x4 ]' o4 B/ M" b# y$ M; m+ V
  14.     /// <summary>
    # G/ {7 h9 J& B) a1 T( p
  15.     /// 离线消息
    6 ^  b% I" o9 E* r6 T: [
  16.     /// </summary>
    + w# |. o8 p3 T1 |
  17.     public class MessageInfo
    0 J' r- L% ~8 _: o3 G0 z5 z; G
  18.     {
    ; c/ b4 n9 E# ]3 J
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)$ |6 r3 ~, e' ?5 l5 J5 |0 @
  20.         {$ ]7 {# N2 }+ |3 F  B2 k# K
  21.             MsgTime = _MsgTime;1 l! c/ M7 j$ ]9 y% d
  22.             MsgContent = _MsgContent;6 e( i, ?- Q8 \0 D1 Y9 ?: I
  23.         }
    3 v' _& H# u  j
  24.         public DateTime MsgTime { get; set; }
    7 B. P1 f2 k6 p- C9 Y2 ]. H- K
  25.         public ArraySegment<byte> MsgContent { get; set; }: k8 r7 D. u5 D! \9 w
  26.     }/ }1 F9 Y) h9 x+ G7 {
  27. ' A  X* Q7 l$ l$ T( j) w7 x" K

  28. 1 [1 `/ B- j; ]
  29. * o) X1 x, q, U' K8 N" }2 ], g
  30. 3 a$ E* k1 g) Y3 g$ I- ~
  31.     /// <summary>' L; z, [- |( J* j6 R' h
  32.     /// Handler1 的摘要说明' l1 B/ }! A! n1 Y
  33.     /// </summary>6 T4 _( J4 v9 q; V8 K6 q
  34.     public class Handler1 : IHttpHandler/ h, A( T" c$ x4 [) W9 |5 \; i
  35.     {
    ) _2 e* T4 P4 v5 Z: ^
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    8 }( w0 Z3 E3 z  s
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池" `' P0 j4 O+ @& B2 c
  38.         public void ProcessRequest(HttpContext context)
    ! h$ X4 L- O6 Q; p
  39.         {1 r( G# C% G+ D" ^* `! z7 R
  40.             //context.Response.ContentType = "text/plain";8 p$ P  V9 V5 g
  41.             //context.Response.Write("Hello World");
    8 W6 k: s1 Y5 k8 R
  42.             if (context.IsWebSocketRequest)1 ^3 u5 k9 l% |, \2 v# b1 c
  43.             {; o, A9 C% X: c5 U, x* z; s
  44.                 context.AcceptWebSocketRequest(ProcessChat);( Y/ @& c1 ~- ~) e! x8 u
  45.             } 3 I. |  K9 q( F
  46.         }
    ; d  J5 a. }: K
  47. 6 n' [, m' N4 S
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    ; p: [& W+ H- N  T
  49.         {
    ; D/ l  R* Q% T
  50.             WebSocket socket = context.WebSocket;
    & l6 b" j0 m  x! D$ w0 U0 A9 O
  51.             string user = context.QueryString["user"].ToString();0 h3 {1 O( e1 j
  52. 9 R7 Q& c% S) ~
  53.             try. F$ o. x* ~2 y
  54.             {
    8 C+ ]+ d. H4 l% [# _) P) k0 D
  55.                 #region 用户添加连接池
    5 b! i5 q& W  @7 r& _
  56.                 //第一次open时,添加到连接池中" M: j/ k( B" M6 S. s2 f
  57.                 if (!CONNECT_POOL.ContainsKey(user))- @' O: e$ F. S1 `0 j$ |/ a: ]
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    7 V5 D) S3 P9 |8 b- l6 u
  59.                 else
    ( k% ?+ m/ e2 Y- R0 L7 B$ p" r# M; V
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新, p5 L1 I% R1 T% W2 O
  61.                         CONNECT_POOL[user] = socket;1 n. r5 {9 q- q9 g& M5 b
  62.                 #endregion
    - S) N% H. w5 Z, Y6 p6 g/ j

  63. / ~% H- N% z8 j$ n
  64.                 #region 离线消息处理
    : `0 V- i% q# k% G9 G
  65.                 if (MESSAGE_POOL.ContainsKey(user))! e& r1 z3 ]6 e) V4 Y# p
  66.                 {
    2 ~. ^4 f# Y1 Q
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    8 [- T# Y( N$ h4 u7 h
  68.                     foreach (MessageInfo item in msgs). E* I! C! h) N: C% J
  69.                     {! B, t. @+ q5 f
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    , _' q" R1 s# X6 }- y1 A! O! L
  71.                     }9 ~, e3 }8 K1 a5 W1 A1 i& Q: m
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    + r3 M0 k; C: j- C9 d1 v2 C* q1 E
  73.                 }
    ( Q( |/ B: l; y: C, h1 N
  74.                 #endregion/ U$ n! G2 I; _% D
  75. " [$ }3 F2 X( z( z/ M1 x2 C7 z
  76.                 string descUser = string.Empty;//目的用户& w$ `" ^: Y5 |; ?; F
  77.                 while (true)- w& d8 v1 f6 N6 G' u+ M& @$ A
  78.                 {5 o9 x" ]" q# a) C- K& \
  79.                     if (socket.State == WebSocketState.Open)
    , {2 E6 o% q- k( U' M
  80.                     {
    8 G: M3 L; ]; Z- h! s5 @! J
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    % t1 D' y* u9 C0 C$ M
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    6 Q8 ?. @8 ~  g) a

  83. ; L! l, d& d  ^* L6 ]' }
  84.                         #region 消息处理(字符截取、消息转发): i& b# q# M" v2 t  x$ }
  85.                         try8 ?7 C; y1 V8 s7 N4 C0 i$ x9 v1 a
  86.                         {9 U4 \% K% B/ I
  87.                             #region 关闭Socket处理,删除连接池* B, D! n+ F' k
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    " N4 s; d/ v" \
  89.                             {
    6 O5 r! K/ T: R4 R
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    + Q# a$ S* L0 w: H) a4 U& x
  91.                                 break;  E( d$ L. G. c
  92.                             }
    " F" c" o3 N, O3 p# ~8 P# M- J
  93.                             #endregion
    & C9 S' j, l) W- [1 s

  94. # C) j* q3 D' i
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息; S; D6 s! ?5 Y8 M$ q
  96.                             string[] msgList = userMsg.Split('|');( k) W* \; A9 E
  97.                             if (msgList.Length == 2)
    * d. t) G3 j3 ^1 _& I: _/ d
  98.                             {" K+ j9 r7 @( Z1 u+ {# p' [
  99.                                 if (msgList[0].Trim().Length > 0)' \- i% d5 N2 O0 _0 c: N  h. N5 g" b
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户. C# g1 F% @, U/ S; H+ h2 q
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    2 m- i' X: v; d* _
  102.                             }
      @$ _. ]6 v. }- s) I4 J4 e
  103.                             else
    & S7 D' h" m, T' m; c5 J+ x
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    # Q7 L# ]7 Q0 n# I
  105.   \& i: ?) K6 q/ K2 q# ^8 Z! ~
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    0 n4 r$ h. |: t4 x5 O
  107.                             {  X, P2 @& x: u
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    6 U+ U4 B% g' R" k8 h8 ~
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open); `8 D) n5 J- P) k" [
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);. r" o# i2 Y& ^2 S. I
  111.                             }
      u! k( C3 I2 g; B: W
  112.                             else
    , j( @; C$ I9 O, b' ^! l; B; O
  113.                             {2 e8 i. H. C! t! ?9 H
  114.                                 Task.Run(() =>
    9 Z1 d; {2 w7 v$ ^+ W
  115.                                 {& A3 s, S% P+ S' w3 T! y6 g5 i
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    ) i) \  s# H0 t  B  x) }* X4 D
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());! `9 V0 j; w$ G$ b3 H
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    5 O6 }6 x+ ^0 L# V5 I# {! G$ `
  119.                                 });" N6 u5 ~: f0 h6 T. b1 F# V: q
  120.                             }8 y" f4 p# h$ h0 ?
  121.                         }" `) ?% ^7 o# ]2 z( E/ h
  122.                         catch (Exception exs)
    5 m4 w8 U0 c- Q9 s4 A. t" {: w
  123.                         {
    / h0 S4 `7 o& ]! b
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    0 T" O# k' o7 |) z: W* u
  125.                         }
    : `! k9 B# P0 V7 M
  126.                         #endregion5 R$ R$ Y$ y  B: }" ]/ j
  127.                     }
    2 }" J2 n6 S, \( b3 B' W) g
  128.                     else
    ) g" |4 N4 o: Q& R( ~# f
  129.                     {  E+ B# S. l4 Q& i6 D$ ^: t
  130.                         break;  {! K8 j! P, @6 r, e( Q
  131.                     }
    / l8 a+ \4 r9 @3 Q& W
  132.                 }//while end
    3 j5 V3 u# W5 _: J5 D+ {& W
  133.             }# ]) V/ E7 y5 K
  134.             catch (Exception ex)" X/ i; |6 i5 y/ `  h: l
  135.             {# v2 L7 w* D& P$ A
  136.                 //整体异常处理
    , C5 i# U/ x7 H$ Q4 z
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    7 N$ z. a3 X5 _6 u: \+ x+ s: ~
  138.             }3 ^3 R3 R6 I3 q0 T0 g+ B
  139.         }
    4 c$ `: ]) P' @/ h8 x" F

  140. 9 R2 z' U9 G9 E+ z$ }+ ^  i: e
  141. 3 @! q& M; f/ V% V4 h0 k/ b4 e
  142.         public bool IsReusable1 g) `& r2 U( j2 z7 [( ]% e
  143.         {
    # O) x. Y2 X  _0 ?" |
  144.             get0 E6 d2 \+ H# @# G
  145.             {# t: T6 d  n5 b5 ~  G7 F
  146.                 return false;
    & n. ~/ w- ~  ~  k. ^4 ~
  147.             }* O$ i5 K; ~9 V6 F. _- x3 t
  148.         }' M2 P  y* A9 d2 ~; i+ i
  149.     }0 x6 X, i7 Y( N6 {, b% ?
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

# Y9 `0 X1 c6 n% Q- H
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-3-17 21:49 , Processed in 0.062154 second(s), 22 queries .

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