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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

5 a- E2 b* k, J, S
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    ' Z! l% B, ?% I$ s- h1 q
  2. using System.Collections.Generic;9 N7 M# R. R2 s! N6 E
  3. using System.Linq;
    ( d5 J, b% ?- A
  4. using System.Net.WebSockets;
    ' S$ z. a# M9 U! \: @) n
  5. using System.Text;7 @! M0 T5 G% K* F4 N
  6. using System.Threading;5 Z7 D4 z' R3 t. ?
  7. using System.Threading.Tasks;
    - P0 M& c+ n  A% K/ l4 L
  8. using System.Web;
    , p# T7 Y* g. }, I1 }$ H8 X3 {) `
  9. using System.Web.WebSockets;  Y' |6 l+ C" c6 @) y! ~. i! F

  10. 5 O5 x7 T$ G4 z0 r. S- C6 z3 M
  11.   k! {! y" N& j, J# c3 s0 ^; i
  12. namespace WebApplicationWebsocketHandler
    & t; b) z/ @; l7 _9 @7 ]  }
  13. {
    + m$ n7 o8 P6 Y4 h  D
  14.     /// <summary>
    ( N% j; ~& F+ h$ k6 j
  15.     /// 离线消息
    - D5 k: T( X5 L/ V& ~9 c
  16.     /// </summary>6 ~7 r9 s6 l1 |; A
  17.     public class MessageInfo: Y4 `# u9 n* k+ z* Y& O& G
  18.     {
    " ]( H$ b  b; L6 }
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    4 O/ o9 _+ B9 u9 {& F8 P7 O
  20.         {
    1 Q# A' i( l# e$ C0 s5 W
  21.             MsgTime = _MsgTime;: N8 x/ _6 y4 k$ Z: v) u% H: g
  22.             MsgContent = _MsgContent;$ L" h/ ~$ r! ^0 L9 t$ o1 C+ h
  23.         }
    4 E7 c  b5 n, I  `7 p) Q
  24.         public DateTime MsgTime { get; set; }
    % k. e' F1 p8 [& ]. L( {8 b; ?7 y
  25.         public ArraySegment<byte> MsgContent { get; set; }
    - W& t* Q& ?- J3 |: b' K
  26.     }
    2 w0 d4 [; m- N9 m' a! K7 |
  27. $ I1 \5 B0 w- }
  28. 4 ~7 e; f) h% s- a& Q
  29. " X' f6 }! |- ^" W' U3 f/ _/ O, g, f
  30.   O$ f5 {0 s) p2 L' f4 M6 F# H) F
  31.     /// <summary>
    2 A( g' \! O- p4 A" W  H( j
  32.     /// Handler1 的摘要说明
    + R- G0 |- z9 H' i$ q  z) p
  33.     /// </summary>
    3 R# I$ P2 B6 T
  34.     public class Handler1 : IHttpHandler
    0 b6 p4 i; B: H) E6 U  m: t
  35.     {
    ; U4 w8 Y( D: N5 W- u, `
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池& ~8 l- r7 T4 C4 W. y6 s+ T* Q
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    % d# A0 `4 I7 |$ Z* G) x
  38.         public void ProcessRequest(HttpContext context)
    ) U, Q: {; k6 o" `
  39.         {
    + T8 U, N$ t* {* u% P
  40.             //context.Response.ContentType = "text/plain";) }* l" s# K0 C( S0 a$ t, u
  41.             //context.Response.Write("Hello World");
    9 B1 m, q4 V* _& W- A' j; _) {
  42.             if (context.IsWebSocketRequest)) x( j. O2 ~* ^
  43.             {
    ! G, P/ y* X8 z! }. t
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    , c) X" S6 R) `7 }- w
  45.             }
    ) H: ~. q" Y. G. @
  46.         }4 `4 ~' r/ U9 z

  47. : I% ?, h, ^& q& L) t% }+ P
  48.         private async Task ProcessChat(AspNetWebSocketContext context)5 ?6 c" h" B; l2 q, a1 X/ I# y
  49.         {4 o+ }1 b8 r" \6 S) q
  50.             WebSocket socket = context.WebSocket;2 f5 g9 X: o/ V4 @. K5 U6 D
  51.             string user = context.QueryString["user"].ToString();& L2 ?+ f: m% u" K* A

  52. 5 P  M# S" R' i5 V
  53.             try  _) z0 [4 S% e- \$ Q$ ?- ~
  54.             {. W* J; z: _% X3 {$ }; y
  55.                 #region 用户添加连接池( D# e2 Q4 J5 X+ z
  56.                 //第一次open时,添加到连接池中
    - P1 b; M; K/ w' u  ^! N
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    . Z' q7 v8 c1 E
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加3 r  G/ B) {7 `* C& s7 g( U# x# \0 s
  59.                 else
    2 Q4 A' ]  a; Z9 y. I- z7 |
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新5 F7 I3 B6 m8 S: {% S9 u
  61.                         CONNECT_POOL[user] = socket;2 F! e% J0 R$ a+ S
  62.                 #endregion% j, F& f3 f9 _* l9 |4 R, O/ Q* j# C
  63. # D# j5 ~) @: h) {
  64.                 #region 离线消息处理6 N$ P8 V: {4 o! z# c2 y' m
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    5 U6 C, ^% q# _7 c) J4 H
  66.                 {
    . h% @! A! {+ ]3 D* O$ h3 w. p
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];* U( q. R0 Q3 z  p: d
  68.                     foreach (MessageInfo item in msgs)
    ; A6 z# D$ U5 {& F! z! `0 D, |7 H
  69.                     {
    % i' b! y: T; f5 Y6 u" N) p
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);/ `* a% B  C5 T* W2 l# G
  71.                     }
    3 @7 }$ j  |- v4 Z% s3 L# P
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    : E$ Y: Y. r* o  I3 G
  73.                 }$ k& L* h5 G# {% a* z
  74.                 #endregion$ w8 R3 A: u) p% U# _4 O) M- U
  75. 9 L) O+ E- F2 w, K  Y" }, g4 k% m2 P
  76.                 string descUser = string.Empty;//目的用户) k1 u4 @, i) L$ Y
  77.                 while (true)# m. }+ [! ?* S# N" Z: {7 [: t
  78.                 {& z9 j, k9 t% }- Y! L
  79.                     if (socket.State == WebSocketState.Open)# \6 N1 q" K6 g6 F
  80.                     {
    . E2 d: {" ^. Y6 T! B
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);( R& s; H8 H0 |) b
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    & A' b. J9 b8 R( y

  83. - C2 w6 i& Z, m3 v. J: p' L
  84.                         #region 消息处理(字符截取、消息转发)& f$ g' I* ^! ^; R
  85.                         try
    # ^/ s; P3 H  {
  86.                         {/ \0 q% p7 J; X
  87.                             #region 关闭Socket处理,删除连接池
    5 E6 w# v. b, f- d% o( e0 M1 j
  88.                             if (socket.State != WebSocketState.Open)//连接关闭8 V. |7 e% F) p6 v
  89.                             {
    , T0 G( k& G; N
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    " m& l! L$ P5 f9 h' o
  91.                                 break;! p% S* e7 X9 c7 ~2 g
  92.                             }
    , K, R9 D* a7 g
  93.                             #endregion; Z9 \5 b2 E: t+ g0 z! U4 K
  94. - v6 g! {* ?0 h0 ?& |
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    - B" [+ F$ R9 ]) Z# j
  96.                             string[] msgList = userMsg.Split('|');$ x. b. a: d- m0 N# w  ]
  97.                             if (msgList.Length == 2)) ~) f# H: Y$ S
  98.                             {
    * i3 R  r  f  u
  99.                                 if (msgList[0].Trim().Length > 0)
    - V3 ]) O( `+ B6 A5 r
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
      l8 f3 Q: u6 ]
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));* O1 [! v4 P- d/ Y
  102.                             }
      A6 R4 R# v# r- P2 ^4 I2 k- O
  103.                             else% N* h+ d. x5 U6 |
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    ; c- j! e3 S+ x' L& n0 }

  105. 0 P! G! b$ |8 ~1 y4 i1 J; n' P
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    ( M  p( n1 Y9 W4 P* Y7 g+ p/ C' a
  107.                             {
    3 O3 a  B7 A. w! u& I1 `
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    1 f* D! o9 P! ]. B  w
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
      _* z% C: ]$ A7 q3 o5 F  ?1 H8 ?, k
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    . t' e) q0 i; A% ]8 `
  111.                             }2 ~$ Q- c$ `& m, X6 }. q
  112.                             else
    ( C# Q" {4 p" o
  113.                             {
    + ?9 ]8 d9 L+ B+ G6 K0 \) y9 t# L
  114.                                 Task.Run(() =>
    5 e& O' r' ~7 y& X  S' K
  115.                                 {( G% ?. W# E4 }% p! W3 D
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    4 c( [2 q7 T* o( {9 Y8 j4 ~8 y, c
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());* `) s7 ?& y1 ]8 J; p' p
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    7 L6 L9 p- ?; ?% F( k2 L
  119.                                 });
    1 Y8 k( h# v8 C
  120.                             }, P3 [) f. Z) r8 v0 K6 D6 t
  121.                         }6 C* U" E) f3 {
  122.                         catch (Exception exs)
    3 n2 |& K. a9 N  w" H1 E
  123.                         {8 Y* c% m1 V7 q5 T' a9 b% o
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    5 R0 }! V6 V" s; p/ s! \
  125.                         }$ i. A8 K- T9 C6 D* B! ]
  126.                         #endregion0 O; V- F5 e0 O2 F, E
  127.                     }1 @# N7 G4 B/ K! ?8 G' s; G- h& ^
  128.                     else) [  _- `/ k' D3 j' B# m, I
  129.                     {2 Z- \+ j2 O0 n9 I
  130.                         break;
    2 g) D- d0 o  z5 @* V
  131.                     }
    5 J2 s6 t' ~" ^8 Z
  132.                 }//while end2 D! v9 T: S  T2 w
  133.             }$ W' O9 m9 P; V
  134.             catch (Exception ex)
    ' @  ^# l4 ^9 k; j- w  I/ r
  135.             {
    , E/ Z3 d; Y! F3 `4 s! n
  136.                 //整体异常处理
    3 s0 R/ }6 w2 Q$ h
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    : Q& }$ l( l3 t+ a# @
  138.             }
    0 R, r+ o) q1 u" r, v
  139.         }  T/ M4 H- ?6 g* S9 N0 O$ C
  140. 5 M: m: h: G/ A, u# x

  141. 2 B  O+ N6 K. Y/ E. `6 Q& X
  142.         public bool IsReusable0 ^" k8 }  n5 \& d1 p
  143.         {6 c  X, K! M+ o
  144.             get/ \, g! J! v; u7 s: q
  145.             {) A& }  [! I- D) q; N
  146.                 return false;' z3 _. F; _7 A6 M
  147.             }9 l/ y; v! n9 r  I! ]4 l
  148.         }
    # w7 m/ m5 l8 z% G+ J
  149.     }' J$ ?7 \( y7 R2 m3 G4 E
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

; t# ~: h' p, {/ d$ n- g+ g
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-19 01:35 , Processed in 0.126464 second(s), 22 queries .

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