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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
8 A% k* O& T  ^; h0 d' x/ @  s( i
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;% w# @) g' |: Z) P
  2. using System.Collections.Generic;+ o. t2 M! t/ k8 }4 i. a% d
  3. using System.Linq;
      h0 F1 K  y, Z/ ?& D* c
  4. using System.Net.WebSockets;
    " \2 s4 H$ ~0 g2 A. d8 R. k$ x/ _) v
  5. using System.Text;. j% F7 I: Q8 l# o6 `  N9 a
  6. using System.Threading;
    1 p4 S& Q8 X1 I. W2 Q- Y
  7. using System.Threading.Tasks;6 L" C& r, k/ a; {
  8. using System.Web;6 V6 ^* s+ m1 N  k: ^  R
  9. using System.Web.WebSockets;
    2 p/ l7 {2 W. l& ~

  10. . g$ w3 J5 V0 r; s8 J  \! x
  11. # F6 A6 a; p+ H/ q; u6 ~6 S) o: O" o& q
  12. namespace WebApplicationWebsocketHandler
    8 c8 `% j! G3 ~0 Z- V$ c# B# s
  13. {
    7 I# v. h, h* k- F: J* z
  14.     /// <summary>
    # n/ Z. }& G) q- _9 ~* O$ v
  15.     /// 离线消息
    4 t1 k/ W9 F1 P
  16.     /// </summary>
    1 C4 W# L% y- q+ R9 Z& H
  17.     public class MessageInfo+ G' ~+ p7 s/ ~) Z
  18.     {
    , p( C* D5 j0 x# P8 @9 |0 N" f
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent), a2 U3 d3 s+ N3 e: i8 U
  20.         {) m7 E) ~& S9 t/ d; A: w" |) L
  21.             MsgTime = _MsgTime;; E( j5 p* o( n& e2 }! ?) J* ^
  22.             MsgContent = _MsgContent;
    8 N* f0 Y7 k; c
  23.         }, j3 @. ~' k3 W( F
  24.         public DateTime MsgTime { get; set; }  Q9 A) k" z: R8 h3 m+ g
  25.         public ArraySegment<byte> MsgContent { get; set; }/ E5 m. @6 j# A  G9 X
  26.     }
    7 ]( s4 r7 k8 Q0 R2 l$ l/ \

  27. ) [. y+ M" s% A8 d7 G
  28. 6 p  B0 b5 P9 g) P) e6 g4 l

  29. 2 l  x5 j) i  a! u/ g

  30. * l/ @# X; p; k2 @. l1 D
  31.     /// <summary>" E% j- V) c- b7 Q' ~
  32.     /// Handler1 的摘要说明0 Z" i* C5 W6 y: X
  33.     /// </summary>
    * D$ w0 u/ p& ~- r% l7 I8 z
  34.     public class Handler1 : IHttpHandler3 S' Z% H) u+ ?/ i  o/ R: `
  35.     {7 c/ G/ p: l  o- n2 C
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    $ a) t" e; ]2 e
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池2 `# y+ d% I/ A( {3 ^/ f
  38.         public void ProcessRequest(HttpContext context)% C3 ]2 e4 {2 m8 _9 T
  39.         {
    % s3 R% h9 z0 _
  40.             //context.Response.ContentType = "text/plain";
    6 Z# I, p5 q" f9 U0 {8 q
  41.             //context.Response.Write("Hello World");( b7 r( w- A8 `& ^& U1 K& \
  42.             if (context.IsWebSocketRequest)
    . ^" [2 t5 R8 Y. b# o. a3 z' u" O
  43.             {
    3 X) t) Q, l; N6 J
  44.                 context.AcceptWebSocketRequest(ProcessChat);; p9 ~" ]6 I6 T
  45.             } ( {( V. Q: Y; T; W% g
  46.         }
    + F* R4 I9 o: E" {/ a
  47. ' }. J9 E) K$ G) s- ~. l; r9 J( _% D
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    5 W4 i: _. X6 [) X( G: n
  49.         {
    % w# L0 W" }8 n1 D
  50.             WebSocket socket = context.WebSocket;$ P* f: h9 {6 W9 d
  51.             string user = context.QueryString["user"].ToString();8 e' r6 {- f% E7 ?' K# z6 a9 _
  52. 6 u5 l" E, ~' {" Y
  53.             try3 Q) R4 ]9 h/ W8 O* ]5 D; ?' q
  54.             {1 ^$ r9 z* |: D7 I) G/ G! j
  55.                 #region 用户添加连接池
    : U& h8 m3 A1 q5 e% q% ~
  56.                 //第一次open时,添加到连接池中  I; ^% H2 Z: l1 s7 ]% b
  57.                 if (!CONNECT_POOL.ContainsKey(user))5 d3 X  G( ^$ J% Z# W  A3 f; t
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加: u4 N* Y* W2 @: ]' }: Y
  59.                 else0 T; M4 R/ v. P, o: v, y  F+ G) u( [
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新+ }) ^$ _5 G5 G2 D5 \2 L) W  r
  61.                         CONNECT_POOL[user] = socket;/ q! M! v! l6 h4 C  e( a
  62.                 #endregion. y& ~( }- x6 n( l& P3 F. J( [. ?
  63. 8 F, V5 a4 U% f# H. v
  64.                 #region 离线消息处理
    . T- z; x! ]7 t( Q* g& N  a
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    ! N  E1 ~! m5 M$ \, A7 _
  66.                 {0 m4 i/ m% V# |7 o, E( H
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];$ K- |4 ?+ B9 G6 H4 F( y& E
  68.                     foreach (MessageInfo item in msgs)  w- m2 G6 ^, q' q  _/ y, b3 c
  69.                     {0 X0 F- F# L/ l" h" Q
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    ' i. |9 t& G$ Q' m4 y" Z
  71.                     }
    + [, |, g6 H, E- K- o% n3 J
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息$ L. o$ v( l% x
  73.                 }* T9 x" O; h2 r5 P# L
  74.                 #endregion
    3 Y. v; X7 L5 k8 |) Q# @9 ^

  75. , i% m3 ?& a! B$ Q+ g
  76.                 string descUser = string.Empty;//目的用户7 m4 C8 t/ i. n: H6 e
  77.                 while (true)
    # D! o$ {! X- H! G
  78.                 {; F* W( t' X9 F/ j& K& g4 h" f; D) L5 W
  79.                     if (socket.State == WebSocketState.Open)
    ; v- u" t" \0 z7 Y/ k; y: `
  80.                     {; I/ ?, Z8 M, v" P4 `5 V
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);2 F  s$ z  i! P# {" F) O
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);, k: y. \5 E2 [' r( }1 t4 Y! D

  83. 0 }& D0 O% a1 ~8 @8 x
  84.                         #region 消息处理(字符截取、消息转发)
    - x: K: o6 Z! s, W* L
  85.                         try5 c1 U8 X' a1 ~5 Y+ l
  86.                         {: q  g1 Y- u5 G* f
  87.                             #region 关闭Socket处理,删除连接池
    / o; w0 E) R9 y
  88.                             if (socket.State != WebSocketState.Open)//连接关闭$ u% d; W, N2 _4 s/ `0 G/ @
  89.                             {
    : F; P& [) {4 h+ b7 f
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    + }+ i; @! V  d6 Z) w, b
  91.                                 break;1 k& I0 a9 d! N/ [6 Y1 @2 g
  92.                             }
    ! R6 N$ f4 F: d; H8 e0 Y2 w
  93.                             #endregion# l9 c% `% `( F3 B

  94. 4 C6 c) b$ V5 B; A$ T
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    1 U6 @/ ^9 _/ ~+ m' Z
  96.                             string[] msgList = userMsg.Split('|');* N5 A+ m( A; n% M
  97.                             if (msgList.Length == 2)
    5 F$ \; e+ P2 J' W+ V9 |; L
  98.                             {
    % Z  H5 @+ B: E# o
  99.                                 if (msgList[0].Trim().Length > 0)5 A0 G7 L% c" i+ Q6 z
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    - A' v  ?( C6 b1 L. [6 U1 \8 W
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    " a" G& X* b5 Z) c% O5 G
  102.                             }
    3 j; j3 Q" Y' n* D8 [
  103.                             else
    7 ]3 A# j& K- ]! G3 X' I
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));, m9 c2 R3 V" G' [2 \* ?
  105. " I$ a3 I, B; ]5 J5 c4 F6 q
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线1 U- a" H& x  H0 L" S
  107.                             {
    9 y1 U& |. Y7 @" c4 \
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    4 t8 G" S! [: q+ V! c
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)* p/ W  |( ^( s, y$ w* V
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    3 e. ]9 |! x/ s6 v% s
  111.                             }
      e' T; H' k2 q4 y4 m* R9 S
  112.                             else' q$ s" ~+ |. Z1 l/ X
  113.                             {
    - ~1 I2 g/ Q5 v; s& F
  114.                                 Task.Run(() =>& r" E2 P; d. W
  115.                                 {
    ! v2 g. \$ A. o' U6 H: `. I7 e
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    . n1 V, J) c! @6 z" h
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    0 Z, S! f+ Y# Z6 U7 Y
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息$ O- r% C# L( o. B$ k9 C4 c& {
  119.                                 });" i: G4 W; _8 r: @' n/ q
  120.                             }- c) W7 z# S. R) U( b6 p. o! ]2 [
  121.                         }+ D4 C& U9 V2 h, t' q+ X
  122.                         catch (Exception exs)) [. l- t% m6 |/ x
  123.                         {
    % k1 E. d9 K2 w* B5 v2 x" I$ O3 V$ Q7 \
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    9 u7 q, k  J3 }2 e  A8 A, d" Z
  125.                         }# @! t- N# b& W+ \4 ~
  126.                         #endregion5 G/ w7 j+ w+ q& d) U, ~# }. \
  127.                     }: W8 g0 N9 U! p5 a; T* @
  128.                     else
    / p- G) C3 N) a( C
  129.                     {( w$ e& C$ n: [6 M& X, Y( k8 \
  130.                         break;
    # U; j# i" M. \2 u; h" J
  131.                     }
    / l5 \) v2 K8 @% g8 ?
  132.                 }//while end
    ! g! R8 Z/ _  N
  133.             }+ r% o/ d, l/ B$ {0 x  l
  134.             catch (Exception ex). d& e+ p- I9 h2 z- P
  135.             {
    # h1 p* R: ]' W6 w' i3 N) H
  136.                 //整体异常处理
    0 o9 x& h/ q: g9 K. w
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    8 k+ |$ J9 s/ |2 M2 k. [$ N# H  I
  138.             }
    4 c5 |, X! x- {" b
  139.         }
    ( I% X' A5 i3 j, E' v0 ?

  140. 6 ?# I# I# |, v- O/ P' ?
  141. ; D; J: Z0 p8 Y) v! r- b
  142.         public bool IsReusable. |$ o% f! c: S+ W! y; D
  143.         {, F8 Y: X9 u) S$ K( r
  144.             get# `' D; G. L! L* i9 B
  145.             {9 [6 A% \; ^2 i/ `0 N1 q
  146.                 return false;1 n8 G3 t, O" V* F
  147.             }6 R4 j4 q* C$ f0 e, A( H
  148.         }
    * \8 U, N  l2 v; ]( o$ T0 k
  149.     }5 j/ {5 r/ j% J+ ^
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

7 ]7 G/ X; v2 t# k5 A- q
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-12-22 18:44 , Processed in 0.131134 second(s), 23 queries .

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