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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

1 r+ l" k, l' l% Y2 E
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    . m: E/ o9 y# x6 E3 p; M8 v4 O4 {8 o
  2. using System.Collections.Generic;* j# d9 S, y  }: T/ p
  3. using System.Linq;
    7 r3 s4 z8 [! }- P5 u( a
  4. using System.Net.WebSockets;. D% \" k# l& k8 D+ o
  5. using System.Text;
    - T: Q4 n9 h/ d* R/ F5 }
  6. using System.Threading;
    . V* ^9 w' `( ^8 k' g7 I3 j" R+ X
  7. using System.Threading.Tasks;
    2 q. x) f5 _6 f1 k
  8. using System.Web;
    ( p% H/ _0 b8 P  _5 t' P) c; e4 C1 n9 }
  9. using System.Web.WebSockets;
    4 Q2 q( I2 s) Q
  10.   J/ o; t/ H( c6 Q7 j$ n& A- P% I. V

  11. 1 c: L' _/ J# }3 i% W3 f
  12. namespace WebApplicationWebsocketHandler3 G4 n- z; M! w  N
  13. {1 t$ q6 L; K) `, c8 u3 D
  14.     /// <summary>
    % V6 X$ M2 H& f, P" V
  15.     /// 离线消息
    0 T7 }* r) @" X
  16.     /// </summary>+ Y6 {; @" k" i: ^( D
  17.     public class MessageInfo
    / v% b1 z; ^5 z7 D6 G) T
  18.     {5 o$ m7 E/ m8 d
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    ; g9 k1 _% c7 z4 N6 _) ~
  20.         {
    1 g  P( K4 g" x. @( }. C$ c- v
  21.             MsgTime = _MsgTime;
    5 s& y' h' P* }; k
  22.             MsgContent = _MsgContent;
    5 s4 b! |" i5 L2 `9 ?1 |
  23.         }: O) d2 o: @# F. C  y  n) ?
  24.         public DateTime MsgTime { get; set; }9 i$ J: ^, N# Q
  25.         public ArraySegment<byte> MsgContent { get; set; }
    3 ?$ Z- V  V) w5 B. P
  26.     }
    / g% V9 o1 J9 Y$ ]; V4 {# d: |/ x
  27. 0 _: ?* `" G9 s- a$ S9 F" F
  28. # Z6 K* {' k7 G$ v" |8 g/ }  L
  29. ) [- g1 O3 m7 ]3 `0 |8 ?5 ^+ E7 N) D

  30. 8 j+ [- \4 F$ O0 {
  31.     /// <summary>; t; s/ {  a- e) V7 E5 L' u5 j3 g
  32.     /// Handler1 的摘要说明
    + W  k: w! P7 T  g1 g& n
  33.     /// </summary>3 U3 d) Z! W4 D9 F
  34.     public class Handler1 : IHttpHandler+ @) Q2 p- F9 G. z
  35.     {. |3 C$ [! h1 X* `4 R! e: x7 B- c- f
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    8 V, C. X5 \% d+ c0 F
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池1 u4 B5 v( R% V' s( B; p$ g; C  L4 }
  38.         public void ProcessRequest(HttpContext context)
    8 D. c6 ]- f: B8 u
  39.         {) W' P/ I$ N) i4 u( H3 P
  40.             //context.Response.ContentType = "text/plain";
    # g, G+ R  V0 H- Z
  41.             //context.Response.Write("Hello World");% H; @) r: P3 t7 P. k- @
  42.             if (context.IsWebSocketRequest)  l7 v! N4 L: w  s
  43.             {
    4 D/ H6 e& _0 V1 a' r" N) [
  44.                 context.AcceptWebSocketRequest(ProcessChat);9 ^- |6 g! F2 {3 D
  45.             }
    ' h. S$ {7 {3 A* w! `% @
  46.         }% k$ N' v% ]3 x( I: o& V
  47. $ u0 P% }, A/ [( t
  48.         private async Task ProcessChat(AspNetWebSocketContext context)- E7 R& g: G& O/ C
  49.         {
    6 M# f5 i, o+ Z& p8 l
  50.             WebSocket socket = context.WebSocket;/ e' Z# p8 n3 e
  51.             string user = context.QueryString["user"].ToString();) G/ B1 }% l1 S: ?
  52. 1 F* X5 a$ n$ i# J
  53.             try, M% F$ q4 S. Y- K
  54.             {
    1 D' |  t7 ^/ [: p
  55.                 #region 用户添加连接池2 O7 u! Z1 @5 F' Z6 y* s4 [
  56.                 //第一次open时,添加到连接池中  _8 u. Y% q; i
  57.                 if (!CONNECT_POOL.ContainsKey(user)): J9 x- v* N" a2 q0 R, @
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加7 }$ Z  i& ^  |' X9 b5 e
  59.                 else8 E# ^5 e+ }; Q0 D
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    ' K9 X& [0 v7 u5 M0 C# |, n
  61.                         CONNECT_POOL[user] = socket;( d  A" a; |% a" N' L* K" c
  62.                 #endregion" C* B- U# R! R' e  X7 D

  63. / q" f& X  F# f
  64.                 #region 离线消息处理& f& G. k( n9 m! }' V# r
  65.                 if (MESSAGE_POOL.ContainsKey(user)). h6 e  M7 O+ n/ u' M/ o
  66.                 {) V0 m# \3 X$ q% ~! R/ X( c1 ]! @
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    : q: o! O9 [* j% j
  68.                     foreach (MessageInfo item in msgs)" C* }2 E* s; {/ a) }+ n
  69.                     {% l+ E* |) }5 Q
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    4 n& Q5 z) S6 x
  71.                     }
    - [! M5 k6 N+ K7 s
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息; z8 I+ K  w- b8 }$ a/ p' Z  t3 r$ Y
  73.                 }' D! }" ?& K8 A/ r9 U/ ]
  74.                 #endregion, c9 h0 r( f) y" Q$ B
  75. 4 d9 G# J( |  ^3 c4 b1 x
  76.                 string descUser = string.Empty;//目的用户& u& r6 t6 t9 H4 l$ ~* m) K! t
  77.                 while (true)4 Z6 v9 L, H2 P" T1 H
  78.                 {
    5 E& s, d% b7 R: Q  ?) w. Y( _
  79.                     if (socket.State == WebSocketState.Open)
    % U; l; k9 K( N  A& `  u
  80.                     {/ i' C  R; D. a- O0 V8 T7 Q* P( S
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    1 j. e" K6 N( r, e2 F3 {, M
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);3 E4 p& d$ u) x0 P& V* ~3 ?
  83. ! ^7 y% J2 g$ E$ u. o4 f
  84.                         #region 消息处理(字符截取、消息转发)
    4 }% r, v; p% o1 G- @3 |2 w
  85.                         try* C& V7 l" X0 F: z& |
  86.                         {
    $ r1 g1 B5 C. T* b, i) X
  87.                             #region 关闭Socket处理,删除连接池
    ! I! a+ }" x- w: J0 Y
  88.                             if (socket.State != WebSocketState.Open)//连接关闭, G, a, L$ l/ z
  89.                             {3 n; z: t( Z# }. ^) X! P% m
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    4 c( n- ~) Z; w; e: e4 X
  91.                                 break;! F7 H1 Z% ^" }" ^' q+ r
  92.                             }
    8 ]/ X& n2 r+ X: v& v7 S
  93.                             #endregion
    & r" S/ p1 W; Q( u0 w# H

  94. 0 J7 J2 [% D3 D3 ^4 B4 C) U
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息5 q6 I- B( i8 p* u
  96.                             string[] msgList = userMsg.Split('|');  [/ c. Z& g# n$ A, \- Y5 A3 r
  97.                             if (msgList.Length == 2)
    6 i+ L5 d4 p- ?; s
  98.                             {( a# Z- q7 ]" l4 r1 B! o
  99.                                 if (msgList[0].Trim().Length > 0)9 c6 {  c6 o) ^- i1 b' c% A
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    ( D; `& b7 f0 z7 @) J$ [# s
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));6 }; ^- m& G8 P- _. _6 k
  102.                             }
    7 N0 T. \6 u; P% q' o, h+ [* Z
  103.                             else
    , e* K) D: Z" n) j% H
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));0 }% f& ?. F* u( I
  105. ! m0 `$ h7 f. M) w# b% l  i
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线. J' Z6 @7 l! Q% V6 }
  107.                             {
    + x0 m/ z0 ?; x0 \% X
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端! `, \+ u% e) ^5 t' r# f
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)4 n% h9 |9 W% R) G0 c
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);0 A: {5 g& s* ]; T
  111.                             }
    ' A6 t+ x/ W& R: ~9 w
  112.                             else
    1 g6 a( `" b5 j6 B$ k( {" w; u
  113.                             {. b1 T. m: A5 q- A: C
  114.                                 Task.Run(() =>$ X# A9 [- M% [4 e9 }, q5 c
  115.                                 {
    . h  G; N2 u: _3 x. }2 N3 q/ F
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    - W5 w% K5 h, j# W9 t
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    5 t( ?  c& _+ e
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    $ X# `( p, ]) V2 g+ e8 {
  119.                                 });1 f3 d/ K# ^# s9 r6 G& r
  120.                             }
    : @) R; y/ \! L1 R( Y* v; t3 ]; d
  121.                         }0 d6 |' \; S8 M
  122.                         catch (Exception exs)+ J, ?0 ^, Q: g7 o8 @
  123.                         {! R# v4 T4 N5 M* R
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息/ w3 D( A! I. m; p
  125.                         }
    " c! W5 f4 V+ ]' o$ p
  126.                         #endregion
    % i* D0 [9 Z5 Q3 }6 i- Z, R
  127.                     }
    7 v& L4 T- K; G" j# I, W) L# x
  128.                     else
    4 b. v  s$ Z# i( ^# R
  129.                     {# X3 I0 l' l; P4 w) L% i
  130.                         break;1 i; V6 A1 A* e* M4 \% ?* }/ ?9 ?
  131.                     }$ a; d, ~- n3 S/ t! {
  132.                 }//while end# k# x3 X7 T9 ~8 I/ Y
  133.             }* U* q3 H) J, h  I
  134.             catch (Exception ex)6 `: ?6 {" p6 `8 h0 i+ ]
  135.             {
    5 r( X/ q3 s* V+ U5 s
  136.                 //整体异常处理9 Q8 u# |* v6 Q0 B; i
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);" V! v5 f) A) G& y+ j9 \% t
  138.             }. n- M+ v( Y8 h5 \' v; s% ~( S
  139.         }
    5 M4 c7 F1 G- A9 N+ m) b

  140. - F, Q$ h' ]8 W6 `  Y8 Y0 d
  141. - ]/ l9 W7 I. p) k- E$ E5 R7 ^+ i
  142.         public bool IsReusable
    " c/ ^3 _2 G' ~& j% k
  143.         {# H  @7 y7 |* F
  144.             get/ r3 l8 l# L7 k( m! @6 t
  145.             {$ E$ O9 h- u5 E! o
  146.                 return false;
    4 H/ T% n# o0 u0 M2 q. ^5 f; _2 u9 B
  147.             }
    4 t$ o# D6 f: B' R
  148.         }
    . U8 x& c7 C5 r" w, A
  149.     }8 W- o) K' O+ x
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

- S: w* p6 Z' H  h
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-1-30 16:21 , Processed in 0.066316 second(s), 25 queries .

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