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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

9 Z/ ^3 d0 O9 R- s
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    , N% @$ x" y; E1 Z! y
  2. using System.Collections.Generic;
    ! S$ r: w, U# x( m0 `
  3. using System.Linq;
    , [! h  U: g5 b
  4. using System.Net.WebSockets;! O8 J. i% K$ d% T+ f: |7 `% o5 G
  5. using System.Text;" a7 X6 T( ~2 ]
  6. using System.Threading;9 T; D+ [' q. Q. j- g7 X
  7. using System.Threading.Tasks;
    % m" E- B; v8 R) K1 p7 B- q+ ^
  8. using System.Web;
    & r; m# N6 b" m0 U5 {; d* V
  9. using System.Web.WebSockets;+ y$ @. K  q1 r! U! }- [

  10. " c  v# m1 ^! W3 e9 c
  11. ( a" Z1 H" C# L+ j+ O
  12. namespace WebApplicationWebsocketHandler' A8 a5 g1 u/ M$ |. y8 ~) U, o) k
  13. {
    0 A# x' |- A5 }# Q. ^" n7 H
  14.     /// <summary>
    ; ^) h$ m% Q. Q0 b/ ?
  15.     /// 离线消息/ Q' m' F" W0 H+ S# ~6 [, p
  16.     /// </summary>
    / j; [8 C4 S) W; u
  17.     public class MessageInfo/ L  d" g2 W% t- S% m' Z
  18.     {( [- X/ M; M; t1 p1 L
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    9 ^% R3 L( T2 |' S
  20.         {& X' l( M! t2 }7 P2 @; `  u0 C. Y# f. x$ u
  21.             MsgTime = _MsgTime;
    / \7 |; O; X; ]4 }3 E
  22.             MsgContent = _MsgContent;
    / N4 g* f- s  r( g
  23.         }0 v0 b3 L0 p& X7 |
  24.         public DateTime MsgTime { get; set; }. A: a* r+ r9 a* u5 g
  25.         public ArraySegment<byte> MsgContent { get; set; }' G+ L7 T$ M* a
  26.     }  f2 I7 \) p! @6 i" J

  27. ! ^' V& s1 O4 [: e: j' p$ M* c
  28. ( r/ z4 J1 S( b& ~0 c

  29. ' b/ A# |) ]$ }- X& i; P

  30. 3 q, v* A. v0 o- k8 S
  31.     /// <summary>
    ( S. H: x% y4 ?& x) k! O
  32.     /// Handler1 的摘要说明6 L" F. Q" S8 D4 [
  33.     /// </summary>+ F2 f- z1 q9 c( p" `# ?5 ]+ n
  34.     public class Handler1 : IHttpHandler( C# x& z- ^. x" W
  35.     {4 f0 @6 A6 P. ^8 v/ ?; `% `. J" v
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池% {  U4 B$ Z( r. b2 {
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    ' E- C3 `8 q+ @6 L$ ]  v
  38.         public void ProcessRequest(HttpContext context)/ d+ T2 s: w) ]) Q7 g
  39.         {
    1 B- R5 k) @3 j4 |6 e  u
  40.             //context.Response.ContentType = "text/plain";
    . L3 H( C3 |* |1 J, Y; }# @
  41.             //context.Response.Write("Hello World");
    8 K; {5 ]4 X7 F. |& t) ?
  42.             if (context.IsWebSocketRequest)
    " W0 B3 q: ^+ W- ]; a
  43.             {
    - ]% L' B3 ~/ y3 d
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    - E( n: ?. G8 ]9 L, R
  45.             }
    0 ~/ c/ a8 W' W0 J3 T. \* v8 g
  46.         }
    ( M* P. U: W0 v  t
  47. / I6 i" K' U$ ?7 v2 b2 r% C
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    ! E9 \& E6 q! o; t1 a9 T; H
  49.         {
    5 C$ D& K1 {9 U; h+ Y
  50.             WebSocket socket = context.WebSocket;
    + }, L, Z& _" Q. |
  51.             string user = context.QueryString["user"].ToString();
    , p% \4 ?6 b( c, d
  52. ) I3 g4 t- \  a% W3 |( _
  53.             try( h. ?3 `* r7 E$ T, V( I3 Z
  54.             {9 b2 j' D/ @, t$ ?7 W: {
  55.                 #region 用户添加连接池! E7 s# l9 s4 [8 X
  56.                 //第一次open时,添加到连接池中4 _7 o, w8 N: q* N4 s% Y1 K* g
  57.                 if (!CONNECT_POOL.ContainsKey(user))8 `7 R# j  S: ~# F2 w
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加! H* e& K" y6 t$ _7 f2 C
  59.                 else
    " }- ]+ q) c; Z
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    / |+ k+ m7 N& Q" M" p6 `4 Q! [$ I  C
  61.                         CONNECT_POOL[user] = socket;4 f4 c/ S# M" t3 D# j% h
  62.                 #endregion
    9 ?  T( |, j4 ]% u/ `8 B; s: `

  63. * h+ e, I1 K0 g( t* S" N: Z2 e
  64.                 #region 离线消息处理& E" c! D$ c* t. s: _
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    ; {& h3 m4 v7 t3 a! e6 D
  66.                 {
    ; `3 r& I0 ]8 x
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    9 P5 G% a7 u) X) w; o( t+ O
  68.                     foreach (MessageInfo item in msgs)5 Y6 D  I# u1 v' M& X' p
  69.                     {- v9 S5 m7 b1 ~' m2 g+ ^
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    : R3 B: P" F. K+ A, s  F/ |
  71.                     }
    - {8 p: E- h5 p7 D
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    - ^  z9 i1 e/ {1 n
  73.                 }
    5 I% @( f, [" Q/ K
  74.                 #endregion5 f) B) T& E* J/ P# E

  75. 3 C3 n1 f% s8 O. s  f) n2 u
  76.                 string descUser = string.Empty;//目的用户4 o9 J) e+ G: C- {* L7 }( ~3 o' z
  77.                 while (true)
    # j" E: f6 g2 B2 l% A) S
  78.                 {9 |; N  T) v0 ]) |4 \0 o5 }5 f
  79.                     if (socket.State == WebSocketState.Open)
    $ a- j  ?4 D% j2 n2 z0 l
  80.                     {- D7 c, t( E3 K) e% S
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);, n7 p1 G1 N/ c9 b2 j8 O( {. W5 I( d
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    9 t8 U  y& g/ d/ }
  83. 0 I- Y0 i* c8 S
  84.                         #region 消息处理(字符截取、消息转发)6 F# t5 f9 m4 S. y' o: \8 E
  85.                         try
    9 M* E! j1 i! j1 q5 J4 d) T
  86.                         {$ u! v# C( ?$ |8 \* x2 r- M6 L
  87.                             #region 关闭Socket处理,删除连接池
    0 q0 E1 K# c4 y/ n) w
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    " }" c- x) P$ h2 x* X6 l* q$ r  w
  89.                             {
    2 P7 h, R/ F6 h2 \. C5 U5 D
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池! l  L$ j6 J8 f1 l) C
  91.                                 break;
    * X2 [5 ~7 V6 ~; m
  92.                             }
    . ]+ g" e3 ~6 h- T. R% h
  93.                             #endregion+ f, N* @4 d% Z* g$ B% n0 X
  94. 4 c6 j1 O9 }; U& |3 q  |, A# p& B
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息: k% c8 P- z6 Q6 q' _' k
  96.                             string[] msgList = userMsg.Split('|');
    , ?, d8 ^) q: A- X* Y( f
  97.                             if (msgList.Length == 2)
    " i: N+ n6 O1 Q+ f* S4 p9 _+ J+ W1 L
  98.                             {0 y$ y. j! H% _5 j9 L! ~4 \7 c
  99.                                 if (msgList[0].Trim().Length > 0)
    - ?7 K% q  A4 V' a( N
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    ; S6 P* L7 g: ~& C0 ]
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    $ E3 y  ^7 ^9 T/ }8 O$ d4 i0 O
  102.                             }  U+ F* h) h+ \! b) V, x# D9 r
  103.                             else# _+ C4 ]# m3 ?9 n1 a
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    9 y' y7 n% u8 ]3 y

  105. " ~: t' X  [1 a& k
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线1 o+ n- g- [' t
  107.                             {
    % o  w" `+ Y2 d' K0 f
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端. c+ b# c5 _$ q( {2 \/ X" c
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    9 S+ O0 @' V6 K! @
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);( @! n1 T* l! m$ }; g4 c
  111.                             }
    - x1 {" W1 X+ H. r
  112.                             else
    % \7 ^" ?3 X: h2 k6 |
  113.                             {5 O9 U1 b( {4 O/ x' R0 T) K3 d
  114.                                 Task.Run(() =>" R; u5 K5 [0 z% b% t% N: }2 f
  115.                                 {
    ) n8 C# J0 g5 U* y) {  c# t0 x. |5 N
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中9 a7 r* O- z" d' e. J$ o; r5 g
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());, C6 ]( C2 V% F
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息* x" e$ v3 L9 ]! \9 J7 _7 a
  119.                                 });/ l9 I  B- ?1 ]9 C4 z) x4 z; Q. J
  120.                             }
    8 C3 }6 Y. K# i4 J
  121.                         }0 _/ O- G& F/ |. L7 `5 \7 a
  122.                         catch (Exception exs)
    9 \+ V- F. l* [% f& O
  123.                         {
    ( \, g, i9 c2 R+ o) h( N) l
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息' K6 j7 L- X  x" ~5 I* G) b3 l
  125.                         }
    ) r/ P. h+ ]( O+ {# i5 P2 w
  126.                         #endregion0 K  F8 U* ?8 a3 L  n$ ?
  127.                     }9 {2 d' _  P8 {8 m( i0 ~, ^. a
  128.                     else2 g7 T  c' n# P. i" q. C( g
  129.                     {* }; N4 k8 ^# q  |3 A+ K* o) G
  130.                         break;. y3 \* z& o) o6 |) v4 ~& h5 }9 \
  131.                     }" u7 u" N, \: u. e9 }" Z
  132.                 }//while end
    + B, R: M$ J1 C4 O
  133.             }( c# N( ?* ?: |4 d9 L
  134.             catch (Exception ex)
    9 _* M; G  A0 r6 m* S# I& y# i
  135.             {/ s( h! y" I" D6 T+ \' }) k
  136.                 //整体异常处理
    8 [. v! o. }- f# X6 C
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    : ]4 e- h9 e- N0 _/ A
  138.             }
    1 p9 B7 v, b2 C0 ]
  139.         }* {- V0 b$ v: Z' B3 L& \+ [; h4 M
  140. . v7 ?! \8 x. O  r; @) w/ ]

  141. ( i+ n# D9 X( `5 ]
  142.         public bool IsReusable
    6 Q+ N3 a) o+ v, ]- ^
  143.         {
    ; |8 s+ B6 a; J
  144.             get' V1 Z! E3 l& |* p+ L, }
  145.             {  X9 r# f2 o7 |( V
  146.                 return false;
    / q& K2 h# o. d/ G( R
  147.             }
    ) u7 t# V' S$ a; j( o
  148.         }
    . H7 h0 a2 Y( {0 N( `; w9 \
  149.     }
    * T. b2 }" L8 w) s* T2 o% A" u( U
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

( ^  k: A2 C& X6 r9 I/ I7 B
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-19 00:27 , Processed in 0.123436 second(s), 23 queries .

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