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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
$ r- Q( m: |; K% h
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    # `) t1 Z% k( X2 h# H8 E) Z
  2. using System.Collections.Generic;
    ' `0 _) o# e$ t
  3. using System.Linq;
    1 R6 t$ @% {0 P! h0 r6 L5 K" r. r
  4. using System.Net.WebSockets;0 O! Z5 _# ?# t4 N' r1 c
  5. using System.Text;' R2 c4 U5 r5 ~- V) f3 j- p
  6. using System.Threading;0 M5 o9 u8 _. U& B$ n$ l* g
  7. using System.Threading.Tasks;/ p# b: `1 B! f+ h
  8. using System.Web;, i8 f' g# l7 m  H  x
  9. using System.Web.WebSockets;7 P2 U9 A! n( Z( ]
  10. # e: D3 I1 s; ?7 Z, l
  11. ) g; f1 y( i7 b: |
  12. namespace WebApplicationWebsocketHandler/ p) c6 q7 W- ?$ u
  13. {( c. G8 |3 i4 H2 t. L: c+ O
  14.     /// <summary>
    " F8 r0 a0 e) P1 e
  15.     /// 离线消息
    5 d# z! O2 \" v3 Y7 S6 Y- f: U; W  j
  16.     /// </summary>
    3 l4 Q( g3 C- B. c, {
  17.     public class MessageInfo
    * l6 Z$ J6 E! ~/ D/ {
  18.     {  x  |8 m( `6 b! `! X4 K8 `
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    0 s5 k) Y- o! F+ I
  20.         {6 Y& e- M% v6 W) z1 _" ~3 ]
  21.             MsgTime = _MsgTime;
    - N4 g5 C- [! ?; v7 L
  22.             MsgContent = _MsgContent;
    ; ^* o& Y6 J1 k: A1 j9 g3 |
  23.         }
    9 R7 [/ o, Z$ b( L# Q  T8 M
  24.         public DateTime MsgTime { get; set; }
    ' o7 T# V$ @3 M+ E: M4 r
  25.         public ArraySegment<byte> MsgContent { get; set; }
    0 Q) ^' ]! y3 K8 L8 [) N
  26.     }
    & ~1 s7 ?+ l' \+ X2 M9 O% c
  27. 4 U3 u! W* l7 L9 v8 |+ b7 R

  28. % u- U6 n4 K( q& ]0 L

  29.   I4 ~  f* w" H; G* D, g

  30. + B2 j, X! H# |6 w* [
  31.     /// <summary>) u4 v2 I/ S9 f6 d7 L
  32.     /// Handler1 的摘要说明$ O$ V/ k* ]/ {3 L) D+ n
  33.     /// </summary>
    & V/ H. k% Q; A% H0 s8 {' c( J
  34.     public class Handler1 : IHttpHandler
    6 z, X4 J' z: Z% B1 Y
  35.     {
    . y. H6 C3 ^1 z" P  F. f
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    : c$ T/ x) U4 [. {& _' J
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    2 O* s- p0 i& h& v% U' J! z
  38.         public void ProcessRequest(HttpContext context)& Y# H) X" c5 R0 Z- i1 ^$ K- Z
  39.         {
      u2 w& G4 K8 y: P( R  u
  40.             //context.Response.ContentType = "text/plain";2 L& @: J" R5 m) q8 s
  41.             //context.Response.Write("Hello World");. ^+ z1 `/ B3 v
  42.             if (context.IsWebSocketRequest)
    ) Q! M* n- q5 U
  43.             {: D  _3 Z0 A" l! a' ]9 G  I: [
  44.                 context.AcceptWebSocketRequest(ProcessChat);5 A3 m' ?" y" q; Y6 h
  45.             }
    $ a2 ~. B0 B2 D* a: w6 `
  46.         }
    ' \& i0 E9 G2 C/ ]. X) A

  47. 9 N5 {2 N' ^9 v3 y
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    1 m/ E- S' B" z  W7 X) q
  49.         {
    ( J8 h* i$ ?% h# q% P! S* g
  50.             WebSocket socket = context.WebSocket;
    " G" V: S: j+ M: |, b
  51.             string user = context.QueryString["user"].ToString();. ~" {$ K/ N5 Y, F5 E% ~0 ^

  52. ! p/ A2 l/ G( Z/ H6 A- T
  53.             try
    2 u1 Y" B- y7 ^, L% V
  54.             {4 H) Y6 {. W% U& Z5 e* ]2 Q
  55.                 #region 用户添加连接池, {7 A9 ~9 |# w4 Q7 F- U
  56.                 //第一次open时,添加到连接池中$ v* t2 b! B: I3 o# Q, u/ D
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    6 R, {  F+ v* n; j" Q6 h. i
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    6 t. i( i4 W/ ?; p
  59.                 else
    8 o+ u6 t: ]7 K" W/ P  `
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新5 |( B7 ]+ L- J1 C
  61.                         CONNECT_POOL[user] = socket;
    , |+ [8 }8 h4 R% M5 n
  62.                 #endregion
    , t% v" `2 g$ {/ T' y7 F4 @6 Q

  63. ) i; Y. k9 F' W' V( x1 S/ o# G# A
  64.                 #region 离线消息处理
    6 W$ n8 s4 s) @5 K. l. G) D0 y
  65.                 if (MESSAGE_POOL.ContainsKey(user))8 ^" I2 G0 R: d$ p
  66.                 {3 R! Y. S6 c# n) _+ |( M7 m- f
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    % w3 m/ ^% d3 q
  68.                     foreach (MessageInfo item in msgs)
    / f! T4 E8 `* C* e6 K0 \" Q
  69.                     {( f" |$ @. l4 w
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    ! G2 c9 o3 d' L1 E! F8 [0 x6 [
  71.                     }2 j2 r2 W$ T  o
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    ; @: G8 N  b" M6 P  Z" q3 c; l2 C8 m
  73.                 }
    - r1 ?* r% k6 D2 J
  74.                 #endregion( Y1 g" q; N; x& p
  75. ; M9 i$ Q+ w% Z) n) Q6 g
  76.                 string descUser = string.Empty;//目的用户
    $ ^$ Y; ^9 N/ e8 {% \
  77.                 while (true)
    & H# `6 ^7 @* E+ C8 y
  78.                 {
    8 A, T, M7 x& L8 H6 q  z/ Y
  79.                     if (socket.State == WebSocketState.Open)
    , A6 w: t0 R1 ?) U2 E
  80.                     {1 [, C+ N0 k( |( P" c
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);5 O- w$ L, N( }; O. }
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    ( A1 c2 [: X+ K4 J6 m. |( J
  83. & D, P5 g! p$ l  ^$ Z* ?' B
  84.                         #region 消息处理(字符截取、消息转发)
    * ~% P/ _- Y& @3 W+ w3 c  o0 Y
  85.                         try
    # _: h3 V0 D: t6 ?6 ~/ O
  86.                         {
    ( |' L# i; H; g" ~
  87.                             #region 关闭Socket处理,删除连接池
    : t0 K/ q9 H: A+ S+ c* H: f/ u
  88.                             if (socket.State != WebSocketState.Open)//连接关闭8 ?7 r4 L, u3 J+ N9 }2 ~
  89.                             {' A! x" d3 F$ x5 H8 v( [4 d
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池! _' g) J* Q! x
  91.                                 break;
    $ f4 A3 I& I4 g/ h' d) m) g- Z1 T, t  k
  92.                             }5 F' \( T7 o  U) g$ G( B3 ^% ^
  93.                             #endregion& ^0 O! `- h  r

  94. & Y1 g, J' _$ _+ z
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    4 q* S7 g) H+ H+ D# H* s
  96.                             string[] msgList = userMsg.Split('|');
    * S- M* r1 [3 ~1 C' r
  97.                             if (msgList.Length == 2)
    3 T' {+ ?) t- j1 j  f% Q0 k
  98.                             {
    / {# h( u! K( U: N# S
  99.                                 if (msgList[0].Trim().Length > 0)
    - |( N  }- Q& d' I9 o
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户* O/ k/ z3 i5 n
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    : k0 U4 H9 e$ h, ]/ G! H0 ]# t
  102.                             }. w4 C: O* y! `# B; \
  103.                             else
    ( z% {# T4 R* b6 m
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));: m& y* V6 \) ^1 T+ D

  105. % J5 O1 \, g3 k  N6 ~/ E
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    ' @$ N# b" x1 I, F5 B4 h( {
  107.                             {1 k) j+ T7 d, i9 S% W1 B8 W
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    * }) l5 B+ R2 {, _+ c. b7 R
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)6 x8 t1 p% o4 K: G
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);  E" b+ Y8 n7 o* \- X4 j5 g
  111.                             }
    ' y4 h! d: |  U2 ]7 d* O
  112.                             else
    7 u5 U2 Y% U/ O/ `, y
  113.                             {
    4 k: R5 `; ~( O/ W/ _
  114.                                 Task.Run(() =>
    # `/ r% g+ v$ @1 ?, h% r
  115.                                 {
    8 h& X) [( n6 S& O
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    # N( W: t: `2 m/ a7 R
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    ; D5 a  t* z% }' E3 b9 G
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    & ~" }" `3 b+ l" e. B, j
  119.                                 });
    * i, Z2 n% ?+ G" z7 L/ W3 h% u9 Q# ^
  120.                             }0 r9 O* z" q) m# V$ H  L- e8 V
  121.                         }9 m+ ~% }4 J5 h/ F  p9 d! a; D# h
  122.                         catch (Exception exs)
    - S4 g4 z) j7 K
  123.                         {1 L% [$ ?5 L$ R5 z; e
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息& r: ?7 E, M& h4 K" ~3 v
  125.                         }) h9 R4 `* [0 }: l! t2 A2 {
  126.                         #endregion" h7 H* C" f, h2 I  v
  127.                     }
    % Q3 n/ a& H+ S6 c( s6 V
  128.                     else) U3 R1 H6 C7 q: F" U4 u4 P% ?
  129.                     {
    * O! {+ z' u" O) |/ P
  130.                         break;) j/ E  O! l) j* Y4 c: `3 X
  131.                     }
      Q7 H! u) _0 O- _6 k- @
  132.                 }//while end
    # Q1 K4 k+ F+ F6 L4 O1 t, P
  133.             }
    0 C( y3 G" V+ J. F4 [0 ^7 l
  134.             catch (Exception ex)
    6 b. t) D) v/ B* o; Z( l! v
  135.             {
    4 y# C0 R8 g* D- [; `
  136.                 //整体异常处理6 U1 o6 Q: p  _1 ?( k+ s0 j( u
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    " j$ V( F% ^! g8 }  |
  138.             }
    $ N" U, J' ^# _6 g5 j' i
  139.         }
    % B& A# O8 S9 N) y6 ]
  140. , S; n  q4 @( O  t9 g" \
  141. " ?8 e' N) m( V( B. y1 R3 Q) U
  142.         public bool IsReusable& w& R6 b5 |; P% }. S6 y
  143.         {3 v: R0 c! `% P+ s7 A1 P
  144.             get5 D- U: f( t/ O. U
  145.             {) I7 `4 f' `7 \9 `
  146.                 return false;
    , S+ C9 `) k+ A& P. T
  147.             }$ b  ?0 k& h5 d& |% `- [
  148.         }
    6 w% N% C2 O2 o5 q
  149.     }9 y9 E7 C) A! m' j7 `
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

. \* v- {" U( [* f. X9 U+ P" e
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-8 03:10 , Processed in 0.122559 second(s), 24 queries .

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