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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

' w0 G7 f+ H! R0 @+ M
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;4 x+ D( ?3 @, P
  2. using System.Collections.Generic;
    1 p6 L2 Q2 Z; V
  3. using System.Linq;
    ! x7 J9 b0 H0 ~- A7 v9 L5 b
  4. using System.Net.WebSockets;5 i& b3 s- w$ u: \, ~
  5. using System.Text;
    ; O8 H2 U# x6 w0 `
  6. using System.Threading;
    + ?  a: K& k% B& k2 b/ G
  7. using System.Threading.Tasks;  d: m# Q& H9 o" M
  8. using System.Web;" d, U& W9 L" ~
  9. using System.Web.WebSockets;" y" Y, E2 K# F
  10. - d3 h; f/ T3 c) T; f/ p$ G

  11. ; E' Q, `# j# R9 m# ?$ ^* E* s
  12. namespace WebApplicationWebsocketHandler
    + r. `" a  o* }
  13. {
    + O7 V( I- S/ I7 i/ G  u& u1 F6 [8 ^
  14.     /// <summary>
    ! Z! @7 C7 Z8 {- ]
  15.     /// 离线消息5 K, F8 M% ?8 Y; F6 o% Y6 k
  16.     /// </summary>2 u6 q! o4 i6 w! s5 @6 M
  17.     public class MessageInfo
    7 X- j: e% |/ Z
  18.     {
    / d3 {5 a' m% n0 |$ W+ z
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)# |9 [; m# V/ N) c7 A
  20.         {
    7 x0 K3 S/ W- i8 A# M4 q- e
  21.             MsgTime = _MsgTime;
    3 R- _5 S+ x7 m
  22.             MsgContent = _MsgContent;
    ( F. o& @6 F- _- W5 [; ^
  23.         }
    5 u4 Y# c4 ]+ d$ |' H
  24.         public DateTime MsgTime { get; set; }, F8 U# H8 W( O* a# u  \3 j" \/ c
  25.         public ArraySegment<byte> MsgContent { get; set; }
    ( Q$ k  m: w- m, \- {
  26.     }
    4 u/ t* B  {) S& G+ v2 \
  27. * Z9 B5 A3 W+ q

  28. ! S3 D* e4 O& N4 T# B) i

  29. $ T7 P7 N) E# g- j( g
  30. 5 y) P* G6 D* x( q6 d
  31.     /// <summary>
    * |  g$ l! _9 q* ~' [" \
  32.     /// Handler1 的摘要说明$ I6 Z! }3 b7 _
  33.     /// </summary>
    ' x0 F& J8 [* L5 I. n
  34.     public class Handler1 : IHttpHandler
    ; x+ S/ a! N. @) e" S1 r6 R( j
  35.     {" o5 L$ J/ q# ^/ Y( r
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    1 g5 e& W: U1 ]
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池' N2 ?3 W& W5 V
  38.         public void ProcessRequest(HttpContext context)( ~+ }7 G3 m. |3 c: Q% Z! @7 s" {
  39.         {, }0 W7 p% R4 X: U) J
  40.             //context.Response.ContentType = "text/plain";' s* W5 b* K. G* Z9 t
  41.             //context.Response.Write("Hello World");
    0 |( H/ d7 C7 s! \
  42.             if (context.IsWebSocketRequest)
    4 Y. g" g) W  Z  @2 d5 l
  43.             {
    " f% i% e; U4 S! ^# e! z
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    - Z2 w9 a, Q0 ?9 Q: ^: @& M
  45.             } " {; `' Q6 h* m- G2 h$ \: p) w
  46.         }
    4 y' L$ j1 F. y1 t' ^! P) n
  47. $ ~" P1 w3 b: N+ F  v
  48.         private async Task ProcessChat(AspNetWebSocketContext context); n, h$ R: u4 U- o- S% \9 d& ]
  49.         {
    6 q7 L5 |- N0 T( n
  50.             WebSocket socket = context.WebSocket;3 Y' ^. r% q- I1 Q5 q5 u
  51.             string user = context.QueryString["user"].ToString();8 o6 ]" ]- H0 F+ J. A
  52. 8 B& O, @, B) d
  53.             try
    9 H, W1 ^& M1 @% W* V( b
  54.             {# L0 m7 E$ Q* {
  55.                 #region 用户添加连接池$ J3 f% S, N) S9 V% `% A. \; F) D" [
  56.                 //第一次open时,添加到连接池中* c0 z, j9 i1 P5 y; v1 u0 p/ c
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    * ^0 ]$ g) H9 `
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    ' ?  {# T# L% q( P/ \  Y& k- R5 x
  59.                 else
    ) j1 A9 [" }* U9 P' h% y# f
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    7 }8 `5 E) c+ q
  61.                         CONNECT_POOL[user] = socket;4 T" w' E( X/ c
  62.                 #endregion% }' v, L( u4 B! z, i/ y5 U9 X
  63. ' {$ D0 t1 ~1 D( E
  64.                 #region 离线消息处理# `- d' x5 e3 Z
  65.                 if (MESSAGE_POOL.ContainsKey(user))1 `! o2 t& e) n, d: Q; R( @- N
  66.                 {" G" L8 ^% b1 a3 N0 U0 N) `
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    # ^. L  d4 S3 ^! s; p
  68.                     foreach (MessageInfo item in msgs)+ D" t# L" s/ n" Z) t
  69.                     {
    8 `( d/ C1 ]  O2 o4 i& o
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);* B* M2 O9 `9 u6 ]3 Q+ L
  71.                     }
    + G/ }" }2 O$ P- a$ }4 |
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息% E- l7 m+ \7 U# r2 V/ {1 @' [( P
  73.                 }( T3 m2 [! m4 Z" r
  74.                 #endregion
    ( T: L" l$ I2 X

  75. 4 T- Y7 W) V/ \* l! ~" H
  76.                 string descUser = string.Empty;//目的用户1 r, Z& b$ p8 y. X# J' F
  77.                 while (true)' W, l3 s7 [0 y7 _- o3 J/ B+ C
  78.                 {1 y( k. [9 V4 L$ O% R: \- l) _
  79.                     if (socket.State == WebSocketState.Open)
    ! X4 h  U$ P  \% j" a' \/ v4 k  i
  80.                     {
    9 r* A2 W/ D6 w+ n) Y6 E( }3 p6 t
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    2 b. s2 G6 R' Y6 Q
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    " L0 n0 i, z7 a3 b7 v1 }, {2 y

  83. / D% `* Y3 B) W% _9 J7 d( O. o" p1 L
  84.                         #region 消息处理(字符截取、消息转发)/ g& S2 A1 t0 Q" |5 R" Q! A! {/ H
  85.                         try' [' u! J- u* f. z% b# i3 g
  86.                         {
      k- d- Q5 I" C6 i
  87.                             #region 关闭Socket处理,删除连接池% Y% `" [) @  l7 o9 P
  88.                             if (socket.State != WebSocketState.Open)//连接关闭" N8 d9 P8 [3 b/ i# _
  89.                             {7 x( T+ L8 [6 h+ e2 _* D5 I  r
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    8 l& ]! u$ p2 N# \) s6 g# K
  91.                                 break;  |1 h, G0 k5 |
  92.                             }* d" z2 a: `8 I
  93.                             #endregion( R) V* [) R- _7 O
  94. + k5 q9 g; k0 x3 R# a: G$ D; V% T
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息6 p4 ^  o9 [! K' V3 b. T1 ^
  96.                             string[] msgList = userMsg.Split('|');
    9 p* u8 D+ w. d# a1 a7 C2 V
  97.                             if (msgList.Length == 2)
    4 B+ E, N* u8 R  g5 Y8 W
  98.                             {' h3 f& t& q  S5 {, x: n! Y
  99.                                 if (msgList[0].Trim().Length > 0)
    / W# {" ^! F7 j$ J9 X( P
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户$ J2 U3 ?3 |; c, y1 k
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    0 Q* H( O& q( l  g: K1 h& q; R
  102.                             }
    3 k$ ^2 w0 m/ s! q' N' p
  103.                             else
    ( P, k7 U8 S) B; M, Q
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));# E8 Z4 ^5 ?; M1 R+ K
  105. 2 M) E4 H8 Y) O
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线$ _* L( o1 N: ^) ]* r/ J7 ]
  107.                             {
    + X- `0 g1 Z) j2 R
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端& X5 _: z0 `. P
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)9 T5 U( G0 l, z6 k  S2 v
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    . C& D# ~8 ?* H% x* e1 J
  111.                             }
    , [+ `' V7 O# t7 [  f
  112.                             else: [- U. x1 l% Y! \2 G
  113.                             {
    9 J. \( s. d) O2 G/ j3 M# P3 V: W0 D3 Q
  114.                                 Task.Run(() =>
    ! }$ i; b7 D! W
  115.                                 {* x+ L8 d) ^# P2 U, y$ L
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中$ H. o' P5 W/ f- d
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    4 T) S2 J; q) g1 E5 b% K% `
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    $ K. B- u- B2 h' X' b& C& e( f  g
  119.                                 });( B- H1 _9 B. t2 Y- s- r
  120.                             }
    " p' z  o) P9 E3 j0 H$ K
  121.                         }
    * f- m& [; `1 b2 i0 n2 V
  122.                         catch (Exception exs)+ a5 p! |6 w- ?8 _
  123.                         {9 C4 e( D5 u* v  |: _3 S
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息. W. f# r- l6 n$ i% P" |
  125.                         }
    & O7 h- c7 i$ W4 G8 K8 e
  126.                         #endregion' D7 c) U- u, u
  127.                     }
    3 ^$ O6 U; @* t# H
  128.                     else0 J. k2 D4 Q: [6 C4 M% K; M; ~
  129.                     {
    ! p- d) a/ |9 K& ^2 T
  130.                         break;; _# F5 @( ^' n% h2 V
  131.                     }
    ( o4 X. Y' @1 H8 X) f! y6 E
  132.                 }//while end+ P4 R. z  N0 g1 A: p
  133.             }) X1 h) D* G$ m+ X
  134.             catch (Exception ex)
    3 ^6 v/ L% B0 R" D8 T8 W
  135.             {
    ! g6 u" h; Y! r! M- ~* U9 N( r
  136.                 //整体异常处理  }( |  E, P/ H7 F' y
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    8 u# L# O) p  Z- u0 F2 Q
  138.             }! E7 v  J$ w  _6 W2 a' n
  139.         }: b; X( f# u9 A+ [# j' r& H

  140. % p) u; T) {, `! o
  141. 1 O% }7 Q1 f+ s: Y
  142.         public bool IsReusable
    * Z5 x8 Z3 H7 v0 _* ?
  143.         {
    % l5 Y# {/ d0 c; V0 c, i
  144.             get7 W1 k6 A0 h: Z. K
  145.             {
    2 q' u8 i- G& @9 M& F9 @3 r
  146.                 return false;
    " z* s* b4 ]  D3 Y$ _$ P9 [* M
  147.             }
    : b/ H' m3 ]3 ^" Z
  148.         }
    4 A/ i; I, ?. W( N! T) `" ?
  149.     }' d5 j% `% {  v4 }$ c% l0 p3 h0 Y* _
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

' O. W! ^8 x* C( J  J0 n& h
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-3-17 22:05 , Processed in 0.058910 second(s), 22 queries .

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