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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

; ?. q. j" ]$ s. y
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;( Z0 e! G! {- {- `  D
  2. using System.Collections.Generic;
    : `, n" d; n# y! ?) U4 G" i
  3. using System.Linq;
    4 K, Q: `$ v$ @* v  [4 |
  4. using System.Net.WebSockets;9 \& c# d" V1 R% p* Q8 {6 F
  5. using System.Text;
    - Z6 d* f; x! K' Q# I: D
  6. using System.Threading;
    9 K1 n& L6 ]3 b* t  C# {8 f# A
  7. using System.Threading.Tasks;
    : K; V$ [9 _! |6 t: `$ Z
  8. using System.Web;
    , o5 e- e5 a9 r$ S" b$ W, F
  9. using System.Web.WebSockets;
    + {! j2 i$ G, |2 o- W5 g3 z7 [: N' O5 i
  10. + X$ X1 s) P( x. W) m9 F

  11. # x& r1 P1 W! y+ N1 M  a
  12. namespace WebApplicationWebsocketHandler+ [8 C7 s, C% ~) H& r: K
  13. {
    * i# _" ~$ r; Z1 v) w, U
  14.     /// <summary>
    $ S. A/ B! H' U, |8 V/ N
  15.     /// 离线消息
    7 S- C0 G2 M" k* m- s
  16.     /// </summary>3 q! ^  k8 o& F6 Q1 I9 M: K" z/ u
  17.     public class MessageInfo
    ' q1 z- C- J$ }) o# u
  18.     {
    $ q# U- }: B' p' M7 ^- _
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    ; \. R, h. z& ]% ^
  20.         {
    & r# O5 i% L7 o1 h, o: G
  21.             MsgTime = _MsgTime;
    ( F) o: h: M) i# \$ z, c0 r/ c
  22.             MsgContent = _MsgContent;
    + k& b5 ]/ N0 u" u
  23.         }4 p; S" _2 q: \# R" W
  24.         public DateTime MsgTime { get; set; }
    ' J' T) l7 h: L7 T
  25.         public ArraySegment<byte> MsgContent { get; set; }3 z! F  Q1 ]6 w  _/ B
  26.     }
    7 ]) ~2 C/ a' K, P
  27. " o; P3 `7 e" R" N
  28. % w! }2 ]  p$ k1 [( O. d

  29. 6 T9 s6 K- y. {- ?" O, ?6 a# R% c

  30.   ?6 F- y" F7 ~1 U5 I" h, y
  31.     /// <summary>1 d8 K. n4 M2 \% Y) D9 j5 q
  32.     /// Handler1 的摘要说明
    * @9 R. O6 ~, N/ M$ d
  33.     /// </summary>
    % B/ \2 B" z$ q0 j! O" Z
  34.     public class Handler1 : IHttpHandler( Y, V. g1 w7 ]) X$ d
  35.     {+ y. W, q( N6 r, ~" z  q  Q
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    1 o) b( |* U" T$ E+ f
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    $ Q- B2 ]6 f7 q- J- n" H
  38.         public void ProcessRequest(HttpContext context)
    + I4 k. O, Z* W! _
  39.         {
    ) r% p% ^, s) ^9 }4 ~% E
  40.             //context.Response.ContentType = "text/plain";
    ' [* a! q$ h0 J+ J8 U2 a
  41.             //context.Response.Write("Hello World");
      _! Q  ~- i- P- U2 l. k
  42.             if (context.IsWebSocketRequest)
    % i! N* {4 W! s5 s5 h: D5 x
  43.             {. B, t& C# s3 T1 O  H2 m: H
  44.                 context.AcceptWebSocketRequest(ProcessChat);: s: a3 V9 ^" E% K
  45.             }
    ( B& F$ s* \. }; U/ ]) s: J9 x$ r
  46.         }
    : @: `& {7 Y1 p' v% I/ p$ T
  47. ' w2 e  G# h" B/ D* h4 p2 F; B
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    2 |: T% \7 K3 T  s
  49.         {
    " u5 J9 S3 {# L1 t) y; a, k
  50.             WebSocket socket = context.WebSocket;
    / o8 k0 z. _4 d1 p% v4 I4 b! A
  51.             string user = context.QueryString["user"].ToString();
    * u1 b5 B+ c4 S2 _

  52. 7 y( W2 u( L; t) u, G+ M4 M+ F
  53.             try+ j9 U# m/ g& [# F
  54.             {" y3 T+ E; U6 B9 t7 _( N9 r6 J2 V
  55.                 #region 用户添加连接池
    ) }. V. y* n& ~
  56.                 //第一次open时,添加到连接池中5 A4 `9 A0 i/ e. ^2 o3 H  [) J
  57.                 if (!CONNECT_POOL.ContainsKey(user))% T/ z* z3 `" I. p
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加. `, |1 E) l7 U( T- ^9 i" t! x$ y3 {
  59.                 else- Q$ R. ~" c/ ^0 H' ?2 c
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    . v: [, x7 X' r4 B. R2 |  F1 y, H
  61.                         CONNECT_POOL[user] = socket;
    . w( B. `4 D5 O5 F9 v% v7 E% r: n6 {
  62.                 #endregion
    + D$ ^& C0 U" Z& i" g/ q
  63. $ ~3 r5 C8 C3 A1 k/ T
  64.                 #region 离线消息处理
    : `# X. W8 l/ k8 U3 ~8 [
  65.                 if (MESSAGE_POOL.ContainsKey(user))6 Y7 K: @) H, c0 K8 D
  66.                 {
    ; L" l  O2 y) F1 C/ ?
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];2 A  M5 b" S; H, D/ g7 M
  68.                     foreach (MessageInfo item in msgs)
    + j& Z7 k6 v7 o* a; B7 q5 E
  69.                     {$ T: y2 Y) {; W3 c- Q
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);# w: L% X7 l6 W9 \- c" ^
  71.                     }7 a0 L1 t" O7 _5 ^' Z8 V
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    % H9 @  o: S# t0 o& c
  73.                 }, [4 E- K: `, [5 n) y4 l
  74.                 #endregion1 {( I5 Z# c  J) T3 r. U

  75. 0 F0 b& a4 X* |. S6 P' [
  76.                 string descUser = string.Empty;//目的用户  \8 ?9 w) l2 ^2 j: U& X2 T
  77.                 while (true)
    ' _: D  f) l; m
  78.                 {
    6 {3 @$ e. D9 e4 H' N" Q2 r  S' k
  79.                     if (socket.State == WebSocketState.Open)4 i! o' T7 {0 j' B8 U' \! m
  80.                     {% D" q  ~! c) a! o
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    ' K3 J" e2 U$ `9 G3 Q
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);2 k0 }5 ?$ f5 G/ Z* s

  83. 4 J% b9 x9 n. }: ~
  84.                         #region 消息处理(字符截取、消息转发)1 W; b$ W- f7 Q: a( g3 O+ j, w
  85.                         try
    0 X9 C+ a8 D3 g" R
  86.                         {
      P# r1 M& y2 @- B. @# s
  87.                             #region 关闭Socket处理,删除连接池/ |* U+ Z/ J1 f1 A# Y
  88.                             if (socket.State != WebSocketState.Open)//连接关闭7 ?- m+ n( f& w
  89.                             {
    ( @7 M$ c$ M0 Y
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池+ t* j/ v' L* q# w# ~
  91.                                 break;8 p7 `3 h1 O) ?
  92.                             }( w2 Z; ~  e/ w
  93.                             #endregion
    7 D4 v+ v+ n5 g8 F0 Y
  94. " L2 F/ s  {. |3 B/ g
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    . C, S0 z7 o6 H7 `, \( d# N, R
  96.                             string[] msgList = userMsg.Split('|');
    : e+ ~" T9 r# A5 t
  97.                             if (msgList.Length == 2)7 n( ?6 Q- F; F, A" c: g  j7 K/ M
  98.                             {
    . N$ C, l6 C) T0 R+ C5 _) ]% a: i$ ^8 z
  99.                                 if (msgList[0].Trim().Length > 0)
    5 e4 d( K' Y5 [( ?/ O0 |0 @
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    5 B9 x4 X: {8 x/ i& {
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));% R% c; E9 `5 g0 \: w9 O
  102.                             }
    & {$ S7 H* `% y" n: d) m
  103.                             else" @( |0 _# P  p" m5 c" I1 I
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    ' H9 W* M- R/ t7 {( u
  105. & M8 j0 j# D' n- E( v
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线6 Y) f0 V+ q  L3 p2 U$ i/ D# U/ L
  107.                             {
    3 r* f; t- U: t4 T/ U: H. M
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端9 g/ _/ s: [# F- O
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    & d9 r0 z" @7 s3 @. K
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    ' z9 s+ M3 l* Z: E" \1 A& m& ~2 @0 Z
  111.                             }
    6 \7 M# f+ v5 `, M
  112.                             else
    / p) J7 D( J( V% Y" K
  113.                             {+ k0 b2 r2 W* e$ r
  114.                                 Task.Run(() =>
    ( l: `/ k" l- i$ l' m8 W6 f# A. ?
  115.                                 {3 c1 ?8 P; h6 |! i7 ?3 M* B: F. }" c
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中3 c; J0 m' P* Z& w( D2 \
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    8 F! m7 r- M0 @# W& \- s
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    - G  [% ^5 `, U4 [! Q' ^$ ~: \
  119.                                 });& [$ K, u: ]* v6 r; p# k% v
  120.                             }
    , U9 [$ N! v9 K! ^* w  d! b
  121.                         }1 c- N! y! v% F5 |  R0 {
  122.                         catch (Exception exs)  w5 h+ c0 b1 e4 u
  123.                         {8 T7 a1 r% W( F; q
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    7 s& f( f& c, i, \, X6 Y5 b
  125.                         }+ i+ d0 z' l- c( ^  p
  126.                         #endregion1 y; p- Z, Y' m  E: m$ P6 {
  127.                     }+ U& j1 ]2 d4 ]6 z& D. U) T
  128.                     else: ?( N: J5 W# Q' B4 i
  129.                     {
    2 \% _% H4 M: }! n" k
  130.                         break;
    / O; c! Q6 a: [1 P4 t' {
  131.                     }& z2 g7 A( |2 j, _9 b2 _, z' @, s* i4 w
  132.                 }//while end
    5 S5 m( ~9 ^0 y8 M: k* K* B
  133.             }
    : `! v+ ?; B) ^- ~; R
  134.             catch (Exception ex)
    : [9 P7 \" I% v4 q
  135.             {  P- ?% S/ i: ~- P. N( L2 F1 m
  136.                 //整体异常处理
    # `4 a& ?+ g" y/ Z
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    9 m8 Z6 i8 q' e: r$ Q5 a# K
  138.             }
    & ~! A# g5 K. x0 W; o5 ?
  139.         }/ b7 v; Z) C% Y
  140. 5 M' h. O1 T$ l. {
  141. ! c' V9 g; f4 D0 R+ W7 `5 U( r2 {
  142.         public bool IsReusable
    * d" O- f' A! ]! ?! O1 \
  143.         {
    2 t9 G9 u7 G9 E3 |0 v- t! i, X! k
  144.             get
    8 g. X& `: G+ e" e0 ~% \
  145.             {4 K5 A: C; y: D- L
  146.                 return false;/ Y' b7 J5 [& y
  147.             }0 q( j6 N6 n, F; N8 I7 l7 r
  148.         }
    2 U, g& L$ j+ `( R
  149.     }
    / L) C, m* F) p0 b5 ]1 G+ q& N
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

" v7 Q" b& v( b) _) U: _& l, x) l
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-17 16:06 , Processed in 0.124663 second(s), 22 queries .

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