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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
$ K0 d% B5 U# S& ^; ~
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    2 t/ B( m+ ]" e  I
  2. using System.Collections.Generic;  _7 D% X2 @1 c/ d# s- A. z
  3. using System.Linq;1 Y! C8 H! v* a4 r; C
  4. using System.Net.WebSockets;8 u$ U  e4 R* u8 T4 x
  5. using System.Text;9 b) X; [3 n4 J3 [  f* Y
  6. using System.Threading;
    ( a" ?1 Z9 K0 ?/ U& W# n0 s3 g1 h0 ]
  7. using System.Threading.Tasks;
    % G* Y- H" Z" J% [$ t6 j
  8. using System.Web;. R* @7 J: h" V) K) e
  9. using System.Web.WebSockets;6 M0 {7 J! j) B0 x$ [" S* A

  10. 3 @: e( ~! f5 [! ~& i
  11. 7 Z8 ^9 H1 R! O  \
  12. namespace WebApplicationWebsocketHandler
    + r3 [9 w( T  q3 z% h1 a. m
  13. {
    1 ?7 C0 U, G1 _# v* ~. ~% q
  14.     /// <summary>
    ; z7 R- u3 _, I% ^  j% H: c
  15.     /// 离线消息7 c' e7 F& o& s+ c0 U* B6 @
  16.     /// </summary>
    & g; B. p; A- Z6 D
  17.     public class MessageInfo8 D/ j# i9 h2 T$ C" O
  18.     {
    & V3 e9 @9 f$ I) ^- U& \3 J0 _
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    ! A7 V2 h3 Z. c. t, x
  20.         {! I# r$ |, B. H% X5 p+ K
  21.             MsgTime = _MsgTime;
    $ r1 J3 n/ Q9 Y6 v/ L( h8 ~) B+ p0 l
  22.             MsgContent = _MsgContent;; }/ ^( @" a! X% z' T6 [
  23.         }
    * N# u1 h7 v% K" v; J* W
  24.         public DateTime MsgTime { get; set; }
    1 k3 K. [/ Z# K! a6 E
  25.         public ArraySegment<byte> MsgContent { get; set; }0 D3 ?! l4 `6 A  a3 D
  26.     }7 }7 _& Q% {6 F! b; w( p

  27. 8 o. i! {( V: D( x

  28. ( t1 c: b: V9 ?# y. n

  29.   z- i2 \5 U# c4 y
  30. 8 I3 r8 y; {1 p! c0 Z
  31.     /// <summary>
    ( U: a  n" ^, l( n& T
  32.     /// Handler1 的摘要说明
    4 x, _8 b6 {7 S; U
  33.     /// </summary>) l' ^# w, k1 m0 @( T
  34.     public class Handler1 : IHttpHandler
    / S: q  U3 J3 M# Y$ W& n
  35.     {
    1 n' H! Y' u  ~/ u# @$ m: v
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池# b, g/ D, k! N4 T% P
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    1 R4 D( K4 m# b+ ?# Y& Y: ]- x
  38.         public void ProcessRequest(HttpContext context)+ H" J  ~0 C" l( E
  39.         {* j! J# p/ i, E" I8 e1 n$ q5 P) Y9 \! m
  40.             //context.Response.ContentType = "text/plain";% X2 H3 d' D6 H. f1 Y: }" E
  41.             //context.Response.Write("Hello World");
    : V3 v* j( a4 d- M1 Y6 ]1 n8 J' U. N
  42.             if (context.IsWebSocketRequest)! z2 |  @+ {" Q0 A2 [# b
  43.             {' E; N& c& K0 ~7 n' e
  44.                 context.AcceptWebSocketRequest(ProcessChat);( N3 C' T% a$ C9 u2 h$ `0 T1 G5 m1 ]0 }
  45.             } 5 j* }4 v* [" A
  46.         }
    ) I& N: I3 v7 P$ ?5 k

  47. * S1 j* ~: x: e5 o/ D
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    6 m6 C$ `% N( c+ r; ~5 i6 H9 g
  49.         {$ F  d, H5 I' r" g9 I% P
  50.             WebSocket socket = context.WebSocket;7 ^/ j( m. Q* a! @; {
  51.             string user = context.QueryString["user"].ToString();  L8 `7 r" }/ A' z# X, q5 K. n

  52. $ S+ ~9 @. k+ [2 a
  53.             try9 n0 j2 t. R- |1 a5 T5 \8 g
  54.             {) e( O2 K/ ^) S/ G# H3 g  U! l
  55.                 #region 用户添加连接池
    2 @0 |' i: t+ D' z1 c
  56.                 //第一次open时,添加到连接池中
    ( j) Y( O. U/ v* B1 x
  57.                 if (!CONNECT_POOL.ContainsKey(user))9 g: I+ f: @. a' ^0 O  |/ O# R
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    7 w( \, a. b- R# b
  59.                 else3 y% y& q! j/ {2 i$ M3 s! U
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新2 x' Z6 L1 i& t3 V
  61.                         CONNECT_POOL[user] = socket;% [5 e- z1 z- l4 u& U4 H7 T
  62.                 #endregion9 ~/ o$ I* |. c$ v* ]
  63. - p& E, h3 k* U/ H; }+ ]6 L
  64.                 #region 离线消息处理6 m: y% n0 C6 J- V8 z! a, z3 W
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    - H2 U% m, d  ~# I' P0 D
  66.                 {( `( [2 ?$ [% Z1 R7 ?
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    ( `* J( `, k3 j
  68.                     foreach (MessageInfo item in msgs)
    1 y5 C5 j; t" ~' w% a8 M/ l+ X  y
  69.                     {) \: z+ [1 z7 l7 A' t
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);& A# q& Q/ W# E1 J8 O
  71.                     }
    2 D+ o( n; X: w, i
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息$ C- _0 V1 m0 H; o
  73.                 }7 J" k$ w8 \4 }, B. ?7 F
  74.                 #endregion
    1 s+ }% Q" y7 o* l3 p6 t

  75. 2 o# F, g, U1 P& ~* n7 V$ K
  76.                 string descUser = string.Empty;//目的用户9 O1 q! D  F: Q1 y* S, a
  77.                 while (true)
    3 X4 }* A8 v+ G5 I+ b
  78.                 {
      P; n' S8 j7 Q  D8 p
  79.                     if (socket.State == WebSocketState.Open)% h8 h% O6 q& \' q7 |
  80.                     {+ B3 L! y, [9 Y
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    . Y5 v& H1 e8 f! J4 P
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    % v# f+ Z6 P. t
  83. / y$ U* N9 o0 g. f/ I, S
  84.                         #region 消息处理(字符截取、消息转发)
    ! C4 o0 F6 W/ ]/ @- b: r
  85.                         try6 g8 T+ i) }8 D
  86.                         {
    0 @0 c# Z% n6 [* u
  87.                             #region 关闭Socket处理,删除连接池. o2 F2 ?6 L4 e( L' i
  88.                             if (socket.State != WebSocketState.Open)//连接关闭. H1 `' B0 c# M
  89.                             {
    3 q+ y* ?3 R% r) I0 `" ~
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    - j- j# D9 T8 p8 [6 B/ I
  91.                                 break;0 [+ \$ H. R7 E' J8 F: a6 ^6 y
  92.                             }
    . J" ?& W/ |; ~$ e6 U% j: }
  93.                             #endregion
    % G. w- |; V, L- W% Z+ N

  94. 0 g( p4 N  ?$ \, d0 S
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    % s  d! y+ i5 c2 p) g; R5 J
  96.                             string[] msgList = userMsg.Split('|');
    * X& w4 h3 Y) t- ^* v4 I+ [
  97.                             if (msgList.Length == 2)
    9 n8 `+ d) j' x. ]
  98.                             {, \; L0 A) u; g+ D: j1 i  H! C
  99.                                 if (msgList[0].Trim().Length > 0)8 I" l  p3 O- e
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户# R; n' t0 h1 e$ ~# [
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));& g$ _6 Q7 E  A* y- ]0 U
  102.                             }
    2 G3 Q  X3 j, x, ?7 Y
  103.                             else% T4 x7 u7 T  b1 h8 j0 W% w1 L
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));- C" ~  W; w% U0 ]& E$ w1 f
  105. 0 u& m) Z$ n5 Y8 P7 h4 |& f& |
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    , l; U. ^# m, \) G  h4 N
  107.                             {
    1 |/ W% k  T% f8 N4 i  y
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    : S/ r1 t. v, y3 y* C9 l" `, ?
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)$ D- O9 n5 u2 C/ \
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    : D9 c1 f$ D; T5 a8 E
  111.                             }! N6 W4 Z/ E( l4 O8 a! J
  112.                             else# `! n" T- w, q/ I4 E- v4 J
  113.                             {
    + x$ O% M2 W2 Q, B% x3 X# u% z
  114.                                 Task.Run(() =>
      v8 j9 X- n: e! g
  115.                                 {/ w( G; H& ?0 _2 W
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    ) ~3 Z4 t: B$ C2 G' i6 @0 |* D- S
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());* H- P/ X: T+ H, t! g, o6 x% {* J
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    - g0 K2 g6 P* p$ c) l  U: N5 W
  119.                                 });
    2 f3 U- P, h$ V. i
  120.                             }
    * p: L% Z: R9 ?% ]. o' |4 l
  121.                         }+ E9 n  l1 Q, u0 X+ i
  122.                         catch (Exception exs)- Q6 |. k5 A/ P! J* g' b  t" g+ O
  123.                         {
    1 L- I$ X  Y  O# y2 x: N; }, ?
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息6 t, Q! _! S! g/ O- J
  125.                         }
    + A# M% |/ O: @6 ?) y! k
  126.                         #endregion
      i! \  @  Q7 E8 R8 ^" s* i
  127.                     }7 I4 z! [. [8 L. }) Y3 {* o
  128.                     else
    * X2 W; k8 B( T- y
  129.                     {: O- w2 a& R, l. t  f! r
  130.                         break;$ ^2 S  c1 f, Z# L
  131.                     }
    8 @, `% n8 E; n
  132.                 }//while end
    # R& D3 z+ U5 d# Y' K$ f- i0 o
  133.             }
    & z2 F5 q: H$ I) ~1 ]/ ?
  134.             catch (Exception ex)
    3 R8 y) i, f  r
  135.             {
    ( M  f3 N1 k' r% s' G/ a
  136.                 //整体异常处理6 P$ _3 R+ w- c6 W! q+ u
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    * C" O1 ^' I( B$ O1 ~2 z
  138.             }
    * N" c4 a. \# g0 Q, g
  139.         }. S. }9 S  d$ Q5 R8 H

  140. , V4 k8 X7 w. S7 S' m

  141. 3 c6 j% Y5 Z; j
  142.         public bool IsReusable
    * s4 m9 g7 p: \1 u# k" _' Q6 M
  143.         {6 P5 k, p! U: Y3 m9 P0 z6 G
  144.             get
    . g0 y' o5 |6 O; h
  145.             {
    . i  V4 Z$ U6 i9 i& h6 F8 |
  146.                 return false;
    ; u3 M0 k6 G: J! x; H
  147.             }
    5 k" W9 ~% V7 F% p2 m' ^) X
  148.         }5 S% B) Y: C: k4 g: \4 E0 x5 t
  149.     }
    + _" ?- {4 ?; ]
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
2 U9 v! S2 o2 v
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-9 12:42 , Processed in 0.112613 second(s), 22 queries .

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