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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
& R1 k- n% Z0 M- _$ o3 U5 `% s" c; r
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    . y2 X4 q9 e/ a$ C" Q+ Y3 J
  2. using System.Collections.Generic;. h$ Q. f7 ~+ r4 j  {. X! {" O
  3. using System.Linq;  Y: i% L$ T: L- S0 T$ x, C: L
  4. using System.Net.WebSockets;
    4 ]+ O- C) d; ?# n0 @6 Q4 c4 p) ?
  5. using System.Text;. H4 x/ W4 H! }5 M
  6. using System.Threading;
    : M" O% d# a$ Y% Q
  7. using System.Threading.Tasks;
    & k* s6 ^3 W: g7 y0 k, \3 g0 Z
  8. using System.Web;0 S8 @& v5 i4 N, ^; L% j
  9. using System.Web.WebSockets;
    0 c  B5 e# \3 Q+ H' n% w

  10. ' r- j# f" e6 n' B" S- }5 G
  11.   Z" ?& p( u: D  m% O
  12. namespace WebApplicationWebsocketHandler5 b% k9 ?, Z1 {% ]' E
  13. {
    . T; q9 n  K9 V0 u% \; t
  14.     /// <summary>
    $ f3 V, b1 o; v' x7 K" {/ ^
  15.     /// 离线消息
    1 B: T  u8 i  \$ t* u4 k; j
  16.     /// </summary>4 c/ Q4 |+ M+ _5 d* L
  17.     public class MessageInfo
    % p. N0 A* |/ g, c1 X6 V6 E) A& G( L
  18.     {
    8 N  ^) g7 ]) h- J
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)* O/ v& X- Q7 q) a
  20.         {: I9 O4 R) ]" D2 R1 E0 z
  21.             MsgTime = _MsgTime;+ w+ C9 ~% i% h; _4 D
  22.             MsgContent = _MsgContent;% g$ u/ x0 O) q9 `; x/ ^
  23.         }
    : D' W" i6 E3 v1 O/ D* w' N
  24.         public DateTime MsgTime { get; set; }
    0 }9 l( B3 l# m! I- d1 b! R
  25.         public ArraySegment<byte> MsgContent { get; set; }  u- G* M3 \5 V& Y$ j! _
  26.     }
    # y% I  B, H" q  K( w

  27. 0 @0 Y: p/ K: ~. s* p7 h* b2 u7 G

  28. # P: s+ U7 c3 h. ~1 t, d
  29. " R3 P! f8 ]4 [0 \

  30. 7 K; R$ z3 |/ S! c0 x# @! X
  31.     /// <summary>
    8 h7 E0 Z) F* Y% p* }4 R! ~) B8 k
  32.     /// Handler1 的摘要说明
    / Y; J: N! V! y" D
  33.     /// </summary>
    $ H4 O, g8 U& o6 H( W- o7 b
  34.     public class Handler1 : IHttpHandler; b5 M, U! v2 j6 l
  35.     {0 r- n0 {3 l2 a0 R  m
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    5 H; B* ?6 v1 F1 f
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    $ R; I& n0 i9 m2 N" |7 z
  38.         public void ProcessRequest(HttpContext context). b) {& {1 h7 M. n- `2 ^
  39.         {" c4 `; S9 M5 n  l, O1 I
  40.             //context.Response.ContentType = "text/plain";. {. p) _% H9 m) f/ m5 X8 C7 T
  41.             //context.Response.Write("Hello World");% G6 [, ]0 N6 [% @4 C3 }9 A2 P
  42.             if (context.IsWebSocketRequest); @1 [; D1 U- F' Q  c
  43.             {
    . |8 _: l, l$ D+ A/ H' L4 ~
  44.                 context.AcceptWebSocketRequest(ProcessChat);, o( t$ |7 ]- u; b/ S4 o
  45.             } # ~& o5 W  @) z; \: L
  46.         }
    : b! X: U9 p2 m. }+ H) `; `$ h
  47.   S: k7 T/ J6 H1 O( \
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    , c0 y. ^- X4 X, L* n
  49.         {0 T- j+ M4 h6 \! T" h$ x' `2 D
  50.             WebSocket socket = context.WebSocket;1 B9 `1 Q6 s( `
  51.             string user = context.QueryString["user"].ToString();
    8 G) y" ?! G7 I7 z
  52. # D1 I  e' r+ F! V, ~  {- ?
  53.             try
    ! N" ^3 U2 o0 \7 e+ h  I/ Q! e
  54.             {
    . [2 L* Q: ?+ R8 |! {* Z( L* d8 L
  55.                 #region 用户添加连接池
    * o: _" X- u& {- ?6 N
  56.                 //第一次open时,添加到连接池中
    3 h2 g9 |- t% S( j0 N1 s
  57.                 if (!CONNECT_POOL.ContainsKey(user))$ }( I" s1 b# x2 W6 F0 i
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加1 v% j3 c1 z% @9 L: H6 j$ r4 \
  59.                 else) F/ e8 c) o4 M* X
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新9 R8 ~7 H9 z  Z
  61.                         CONNECT_POOL[user] = socket;
    9 T5 i* |- ]2 d' _
  62.                 #endregion0 ?; N1 r- G. g& d3 D
  63. 0 \! K' {4 B$ H. y
  64.                 #region 离线消息处理0 ]% t# g  C/ O6 p
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    ; ^* {$ g: H5 s2 b
  66.                 {
    ; {. J) Y/ w2 K: Z1 q2 ?
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    ( ^# _& E( }* E8 p: s
  68.                     foreach (MessageInfo item in msgs)' p. p0 i3 K5 n1 V7 u3 u
  69.                     {5 a4 R* l4 @! T+ P9 Z
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);/ e/ k3 \9 [* m! S& n$ l
  71.                     }2 C2 a: ?8 ?; J& ?. d4 t# o0 P
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    3 Y/ b: Q$ K' v7 u4 y( s
  73.                 }8 S9 k$ o3 D, t6 \- Y6 B
  74.                 #endregion
    5 S3 |& e, Y% ~# m, |

  75. ) R3 m4 r+ M# o  F
  76.                 string descUser = string.Empty;//目的用户9 |5 [3 W+ n% n3 G- q0 {- a
  77.                 while (true): ^. X5 E7 d% k
  78.                 {5 V, z3 E4 c& _
  79.                     if (socket.State == WebSocketState.Open)
    , t$ d5 j9 d! z3 n1 Q
  80.                     {
    ! f4 Y; a3 W2 J6 J- K# q
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);+ h/ {% l7 m: M$ d& Z
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    1 @4 O/ p1 y! `7 x

  83. 2 m; Z* p# J2 ^5 _, _% Z
  84.                         #region 消息处理(字符截取、消息转发)
    * O0 a7 r( ^8 i, `
  85.                         try( D5 G& {$ K  h( J
  86.                         {6 y' m# |$ J7 {2 z
  87.                             #region 关闭Socket处理,删除连接池7 P8 o% C* D/ V9 O0 R  p' U
  88.                             if (socket.State != WebSocketState.Open)//连接关闭' l6 `6 E( \1 p) J1 c" ~
  89.                             {- [2 g& \) @+ k
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    1 Y  r( q* b1 p
  91.                                 break;
    " M. ?4 d7 u. }) U
  92.                             }
    - C" I9 w0 E( @
  93.                             #endregion' l$ o0 D$ T2 _) c' Q6 _
  94. 5 W" \8 R: R5 T$ |# O9 v8 U
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息2 s4 R. F& G5 _7 W1 M8 t* c
  96.                             string[] msgList = userMsg.Split('|');' q0 @5 J1 ^9 n6 l% n: t4 z
  97.                             if (msgList.Length == 2)
    . h4 ~' r6 `, @4 Y1 R2 M
  98.                             {
    # H8 E# [* |3 ~& d
  99.                                 if (msgList[0].Trim().Length > 0)2 T+ P% F# x% `% C9 s8 ~  p
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户7 Z, |5 g: l0 B) }5 N8 j3 [
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    0 S: J) R; a  ?" k
  102.                             }
    ; h0 q/ D4 B) ~1 I
  103.                             else
    , z3 r6 V9 A$ {$ P! E& Q
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    4 W, ]1 P( _6 I! `) ^* P
  105. - H8 q( [8 W0 Z8 v' s& s1 P4 \
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    ) n  w2 d2 E/ o/ |, u
  107.                             {1 R" v2 q# |' g
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    ! O  o* C8 b" d( Y9 s* y- K3 I
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    , h8 A. c6 G! ]8 D
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    ! g; j* V. p* S, w+ {$ C
  111.                             }
    $ Q  v7 m, J( Z: g' Y$ K. C
  112.                             else
    0 r" }& E/ j% l% t7 S
  113.                             {
    2 N# }3 U/ a/ t4 X  D: }
  114.                                 Task.Run(() =>/ n* G3 h# Y: R0 |& j2 P8 I
  115.                                 {" z" I; I: s! N1 }
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中' x7 C! J! X- S3 G# ]) |
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());0 v9 ?: k5 A7 N) V8 O
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息4 k& D* C. F8 L6 w; d8 Z
  119.                                 });
    7 l' H6 f! Y& L2 b$ I: b8 Y6 ]
  120.                             }% k& u; n3 K5 r( W1 o& F6 _$ G- k
  121.                         }
    * l4 B; k* D; f; [0 c3 o5 C) q$ D# ^
  122.                         catch (Exception exs)
    & q! G. _- y% j' k, d0 U
  123.                         {- A  r" B0 m" s/ v& n
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    $ g) n9 N. O7 j1 l' [
  125.                         }
    ( z0 i9 J5 S. L2 M& V9 n3 W' H% I
  126.                         #endregion' `4 y+ n  Y9 B1 \& t0 e) y
  127.                     }
    4 i1 z6 V5 i, r) o
  128.                     else
      I$ q" U, z/ Z+ o: f# b: N
  129.                     {: u  |9 K* M' m
  130.                         break;" |6 o+ P% V" ?2 n
  131.                     }6 q6 `* L9 G0 s3 w+ o
  132.                 }//while end8 v& c$ o0 Y, |
  133.             }
    ) H8 i% ^( V5 y/ _
  134.             catch (Exception ex)
    9 Y3 }7 V* H1 N3 _( j  m+ ]
  135.             {
    : A* `2 ?" F; X1 R5 T
  136.                 //整体异常处理$ V; G: m, C# h5 b4 f; B. D
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);; P: _( \2 ?9 c& k  J
  138.             }
    4 c/ E/ z$ F4 J1 M( ?0 t4 n5 c
  139.         }! K' V5 }% ]& r3 M
  140.   e; J8 t  l3 U# O+ d% ^6 I
  141. ' N, t* g2 W2 t; P; k4 ]
  142.         public bool IsReusable
    # f# K3 r3 U$ p& t7 K7 R2 k
  143.         {
    - A- B3 S* F" c4 j; F& h! X( `
  144.             get/ X8 Q. k( U8 t4 a) i, b3 K2 G4 b
  145.             {0 N3 d' Y0 \* H; n8 ]! E( w+ E
  146.                 return false;
    8 u7 r- f5 N* }3 o: H
  147.             }
    7 J; h, O% f2 g! u: d7 `
  148.         }
    & m/ e: |$ K7 g' [; c
  149.     }& C  f% v. `/ l
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

( T. B& ?% G5 t6 ]6 r& h1 b
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-6-20 03:13 , Processed in 0.062756 second(s), 23 queries .

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