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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

1 L: k) D4 C: Q$ I
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;' G2 {; Q. @" D, W
  2. using System.Collections.Generic;
    & [/ }% u1 j# N7 e8 ^1 n: _
  3. using System.Linq;
    5 `* r5 D- {6 D& g$ t# R2 {6 I' z
  4. using System.Net.WebSockets;" k9 F2 z/ N4 d9 v4 W/ n
  5. using System.Text;
    " u: ]. l" {  l# [" o4 a
  6. using System.Threading;* k, [4 C* \+ o6 Y6 t
  7. using System.Threading.Tasks;
    ' p! v% ]0 ^" L7 ~) t% z
  8. using System.Web;
    & q' {9 ?$ o3 [" {6 q: B
  9. using System.Web.WebSockets;
    " ^- I6 c1 q" Z4 E2 T0 c

  10. / G' R& R3 w6 C" W& O
  11. * X8 k/ J# d0 `
  12. namespace WebApplicationWebsocketHandler+ |. T( ^/ I" D0 z6 z
  13. {
    5 U1 j/ {% v# b5 l( a
  14.     /// <summary>$ b8 E. i$ E9 F& \* H% M/ s' b
  15.     /// 离线消息
      l% L" T; Y3 ~$ D" s5 z# e
  16.     /// </summary>, C0 W. U+ S- `: c7 `2 ?6 S3 K
  17.     public class MessageInfo! I- h: ^1 J' J  P
  18.     {
    * t1 `# ]3 b7 P! E; R: }
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)7 G' h& a1 Y7 y+ z0 I
  20.         {& ^& ~2 y2 ^9 n
  21.             MsgTime = _MsgTime;) L1 _$ I3 |  r9 D( X
  22.             MsgContent = _MsgContent;
    $ C  o" J& a: M" u% [
  23.         }: F1 D8 y+ m* W& ]& \, d8 `' R
  24.         public DateTime MsgTime { get; set; }
    / |9 q: S, M* S/ `
  25.         public ArraySegment<byte> MsgContent { get; set; }: j; d, J) z6 o* m+ ~- b3 B
  26.     }
    0 V, r4 J6 Q, n2 t6 }- |1 Y6 ^

  27. 4 B( Q. A/ j' f  i8 T
  28. ( L0 x1 I* G4 N6 ]* ]5 ]! ]
  29. . G$ M6 q& v! I) F
  30. 3 ]2 U3 m7 ?  _  b
  31.     /// <summary>( a5 K# k& R4 U7 c3 i" {
  32.     /// Handler1 的摘要说明
    * Y0 x1 @7 E. Q8 T
  33.     /// </summary>
    * X# k  U! I# d; n
  34.     public class Handler1 : IHttpHandler' y4 q) S: l, G' H
  35.     {
    ' ?# K- z% \  H3 f1 c# e( I" ]% [
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    ( v4 Z! k/ ?1 U) c" [( r
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    . i; C5 j2 j, v) o* S9 N
  38.         public void ProcessRequest(HttpContext context)
    " u5 L! N; e* U
  39.         {: {5 |+ s5 E' B) v
  40.             //context.Response.ContentType = "text/plain";
    - a& p; h: q% }8 }% |2 S9 _, t
  41.             //context.Response.Write("Hello World");; h  K6 e7 E4 J
  42.             if (context.IsWebSocketRequest)
    - p& b7 U/ d1 l6 d" r9 J
  43.             {
    & c" u0 b9 F6 ^8 h0 d
  44.                 context.AcceptWebSocketRequest(ProcessChat);: o  s( x) y4 R) S- K# b) `6 U
  45.             } 4 s( p( a" m& M" ~  }
  46.         }: F+ b  j4 x* B' `3 v5 j
  47. ) T3 ~, Y4 s' n5 y
  48.         private async Task ProcessChat(AspNetWebSocketContext context)# `7 g$ N) ~# D, J. A
  49.         {. ]% G9 F9 _; r& _( J! O% C
  50.             WebSocket socket = context.WebSocket;
    + \  `& [. w5 k3 O! l4 F: [
  51.             string user = context.QueryString["user"].ToString();
    9 L+ c# a- ~" x

  52. * S6 Z! y' b9 }. U
  53.             try
    . q7 X& B3 c& _% n$ x4 x2 z0 ]
  54.             {
    . v. k/ z# N( e- X* h4 r
  55.                 #region 用户添加连接池
    * Y4 M! `6 H4 _  L) G  d
  56.                 //第一次open时,添加到连接池中
    1 i- ^0 g2 J, o, O
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    7 d6 h# A3 A. ^$ I/ m' \2 x4 j
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加( J4 H; a) S3 R( Q0 f: W) o
  59.                 else
    1 R5 J& x0 v& a+ O8 \
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新* s. V3 b. a2 a7 v
  61.                         CONNECT_POOL[user] = socket;
    1 e2 ~( m" T" i8 a
  62.                 #endregion' r; Z  }0 b0 F$ Z( I2 j

  63. 8 q( J% ^2 \# m  ~2 B
  64.                 #region 离线消息处理1 h3 X/ J5 A, Z( ^2 x% D: ?+ j3 e! J$ Y' H
  65.                 if (MESSAGE_POOL.ContainsKey(user))  n1 C, l: A) Z5 S
  66.                 {* \; h- }: L) S9 _% o
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];0 P) y% D) L; g" V% [% ~
  68.                     foreach (MessageInfo item in msgs)" K4 X) ~' i4 `
  69.                     {
    6 |; @/ J- N8 t$ t3 R
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);. T+ c" @  U1 K6 `
  71.                     }' K1 p0 S: i; i' O) R' I
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    ) e% R3 e1 G! R- C/ E9 l  i
  73.                 }
    ! y9 K1 i9 r5 v" O' {- Y/ A
  74.                 #endregion
    5 V, d3 Y& @$ X% o" n+ g
  75. 1 B" {) Q' y% O- r# W" Q2 H
  76.                 string descUser = string.Empty;//目的用户, g3 K5 ~# d8 Q. I0 G5 w1 i
  77.                 while (true)( D/ x/ A% A6 {# q7 m5 M) n
  78.                 {
      o$ U; w( [0 F! g% b* @9 Q$ `
  79.                     if (socket.State == WebSocketState.Open)7 {8 Z3 [; t' w8 v% H& m
  80.                     {
    8 y: |0 T5 j# v3 f: [$ [
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);( v2 W7 p  ~) ^
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    , |1 B" x& _7 y
  83.   D- k+ B; |9 d6 j
  84.                         #region 消息处理(字符截取、消息转发): A. X& Q; y5 N, d
  85.                         try
    ; G; W) r! ^% T
  86.                         {, O% H& g* e: a* G4 b. T. c
  87.                             #region 关闭Socket处理,删除连接池* @& j; r9 {% N
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    1 A5 A. e' p" P5 w+ c
  89.                             {
    2 q' S1 A0 Q8 o1 r5 N, U
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    4 [5 a% B. Z. x+ h9 }% G
  91.                                 break;
    + r* S: r# Q8 I: u$ P6 p5 _: f
  92.                             }
    + ~, T! n) w) C, t
  93.                             #endregion
    ! J4 ]3 X9 n, J0 t9 T
  94. 3 K; W+ ^; u0 ?* ?6 U* F
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息% W' t5 Y* ?' Z& v  A9 ?& w
  96.                             string[] msgList = userMsg.Split('|');9 m7 h* Q4 Q. y& @
  97.                             if (msgList.Length == 2)
    5 x( c& `, D9 `0 @$ H6 l% X# e
  98.                             {7 k! V( Y$ Z! T: ^
  99.                                 if (msgList[0].Trim().Length > 0)
    # l8 `; B- T# u9 r! g
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户4 C5 q5 M9 S! O5 _" w5 H! M2 U
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));. c  e0 `# y- d" Y& @. @% s. h1 x
  102.                             }
    * ~8 w9 S: \  v# Z. I
  103.                             else
    : D0 K3 ^- p4 C& f9 q' |' k
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    3 [, e5 z0 g! _* P  r+ n& [
  105. / b% s$ `( ^  N: n3 H1 w. x+ X7 c
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线; `) c. D0 [6 @' b3 n
  107.                             {
    6 g4 n) C2 z) p" g+ L" b/ m9 y4 S
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端) G( h; G3 F( `0 }+ G# P
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)3 v* S% R7 G& c7 y' b$ Y  G7 {
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    + a4 Z* b1 T" L: C
  111.                             }
    $ h! ~* C: q  w! R
  112.                             else5 D7 d  b8 F/ A4 m. }8 G9 c
  113.                             {1 ~* `5 `5 a( n# o
  114.                                 Task.Run(() =>
    ' h( l3 L+ f( p
  115.                                 {
    3 e) F5 p4 t! w& l
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    & t: a( b+ Q1 ]8 Y6 o6 |; U
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());6 k* @0 l0 E7 n, U, @" u
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息6 U2 F7 g$ s0 ~9 B+ m
  119.                                 });+ B8 g- p/ ]+ j; K( I8 `
  120.                             }
    % U0 |5 T# m& t
  121.                         }
    1 q/ Y5 O( j  u, z
  122.                         catch (Exception exs)$ K, {$ B' g, [- J# f
  123.                         {6 f8 b/ T3 W( V& G: z
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    1 }! U( c/ q  O: J1 ?0 Z/ J% |3 ]; Q
  125.                         }
    - J( o2 B, ^0 D0 A# L& T! Q- M
  126.                         #endregion
    3 W/ L( m* O4 U" ?$ Y  l# E: N
  127.                     }5 R9 z- V* K: p; L" T+ d
  128.                     else7 \9 Q8 \  p4 U+ {
  129.                     {
    ) h8 _" e3 ^+ ?3 \* W
  130.                         break;
    0 q8 H8 G+ V' b- l) E% C
  131.                     }/ ^4 r! f2 V  D& {* k
  132.                 }//while end
    : [' B) d, _0 P8 A! U
  133.             }
    * A; X4 K  a! r! J: H! ~) u7 r
  134.             catch (Exception ex)
    8 N, e' Y% R& P7 M9 O
  135.             {* y6 r$ I. C5 ]- z0 b' j
  136.                 //整体异常处理
    : P& d9 g7 p( s: m9 q& U- X, y
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    / r9 A, n$ d( S! Q! y; u3 b' u
  138.             }
    8 S: k5 D# H* i) |8 c" Q9 V
  139.         }  H7 p8 b+ f; X

  140.   a7 K* c; ~5 G1 g( Z

  141. ; U' x; ]# M6 K* \7 R$ U
  142.         public bool IsReusable3 p9 @, h; U/ ^9 z* V5 a" k
  143.         {
    1 Z/ {4 M9 \$ C5 b' `& ^( z" W
  144.             get2 @1 A* N5 G( o0 ]3 ?
  145.             {
    ) o& B4 W, r+ Q/ A
  146.                 return false;
    % ~- V/ r: b5 z1 k
  147.             }/ u: y; y" R- d: ^% N$ p8 w
  148.         }
    0 I. G) E: q2 h2 x
  149.     }; D2 e! G& l8 i5 {9 u5 p
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

- b2 e7 R6 c9 r! y0 i% N
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-6-20 02:59 , Processed in 0.057459 second(s), 23 queries .

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