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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

5 K3 S2 o% P1 j% }; t0 _
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    4 b* B1 r2 @% c8 T0 ]" C
  2. using System.Collections.Generic;- [5 r, \' h- L
  3. using System.Linq;* T- v3 m- g# E' S9 y* j6 d
  4. using System.Net.WebSockets;: Z8 n0 }/ t3 W5 c
  5. using System.Text;% V2 t2 F& m" v" I
  6. using System.Threading;+ {4 H, |$ T' J6 ~' N0 z4 m
  7. using System.Threading.Tasks;" e8 G5 k4 j) H% l9 n' I
  8. using System.Web;
    ( T- K, I$ B: H, N
  9. using System.Web.WebSockets;
    1 e$ v: E- f( ]) z1 I1 E: U

  10. 1 u1 S/ C1 Y% w9 @5 o8 F7 h& c9 H; |

  11. : \" E; ^4 v& {# H$ o6 E
  12. namespace WebApplicationWebsocketHandler& V; [) p% O3 O% O; H7 G4 G
  13. {6 ]3 q& V# x4 r. {% X
  14.     /// <summary>
    ; \; {* N) C( m1 u! x% i
  15.     /// 离线消息# I: B7 F% _% h$ J$ P
  16.     /// </summary>7 ^0 e4 _1 x( j- h7 [  ?% z6 q
  17.     public class MessageInfo
    7 w, Q) b: m( ^5 k4 r  o: |2 W6 Y* B- m
  18.     {2 E0 p" Z9 w: W0 l+ C
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    / Y- H0 k* ?! G2 P3 h
  20.         {
    6 R# K- u2 t, C- n, z( S) F6 Q
  21.             MsgTime = _MsgTime;
    4 a) Q9 I4 ?; t+ R( n
  22.             MsgContent = _MsgContent;+ U) g! d+ k1 N! D
  23.         }
    ! W6 W' @: H- z' J& @  R" k
  24.         public DateTime MsgTime { get; set; }9 {6 s, X: g1 }* e3 K0 A8 [
  25.         public ArraySegment<byte> MsgContent { get; set; }
    0 G! e& I) m  Y
  26.     }
    7 s' o7 L0 ~; f

  27. * e6 \) z( Y$ {4 n0 K
  28. 5 e+ I, W5 @: v  `( Q
  29. # j/ `. z, E: U3 O! U

  30.   h+ T( \/ ?& Q5 U3 V6 f3 a
  31.     /// <summary>7 y9 @- f$ X% S% [" y; u3 c% m
  32.     /// Handler1 的摘要说明
    & h  Q- B* M9 n" B" r& Q
  33.     /// </summary>1 J$ m% W" ^" u4 c
  34.     public class Handler1 : IHttpHandler
    * I# g/ @7 b4 R) A5 d% S3 R
  35.     {& B" Y* H. c5 a  R' O
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    / W: V; k% F3 H" n7 q. U
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    & v2 h  y& x, B1 H6 S' {% t
  38.         public void ProcessRequest(HttpContext context)
    5 c7 I" I! V8 ?& L" f/ K2 c
  39.         {* o! F9 E+ G( q
  40.             //context.Response.ContentType = "text/plain";; q% ^6 [, q! ^# k
  41.             //context.Response.Write("Hello World");- s6 b8 w8 l* P: I/ d$ r2 N! B
  42.             if (context.IsWebSocketRequest)6 E9 F2 j3 ]# m4 Z9 W
  43.             {
    6 W; G% B; D: I6 d9 \/ A
  44.                 context.AcceptWebSocketRequest(ProcessChat);: o, \0 U) D! S7 f4 \) }6 {
  45.             }
    , U6 a5 s! W0 C; `9 j
  46.         }: `5 C* Q0 w( k
  47.   ^0 [/ p4 _  j& G1 ?: D2 @
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    4 i! h, Z8 W2 c2 Z3 o2 d  w
  49.         {+ P' x6 G0 B: a3 s
  50.             WebSocket socket = context.WebSocket;" W* Z5 e- ?8 t9 `( Y! Z
  51.             string user = context.QueryString["user"].ToString();
    $ A5 ~; o- A  l$ ]
  52.   t) p/ d0 G3 z8 B
  53.             try! J/ C! G  w' ~$ ]. F
  54.             {  a" |& H- t0 P
  55.                 #region 用户添加连接池" {: u6 V0 V  G2 Z% X
  56.                 //第一次open时,添加到连接池中
    1 u6 z! O+ Y% R( t) G
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    # X/ \) i, m6 Z1 S9 F9 x
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加( x: w8 N8 C! F+ t5 x. t& J
  59.                 else1 P* B. ^4 a, u% Q4 ]
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    - t# ?5 }4 L- G7 Y' a
  61.                         CONNECT_POOL[user] = socket;
    % ^2 |, ~6 f$ \3 C
  62.                 #endregion% `/ a7 o8 S9 g0 P5 [4 n
  63. ! }; L- @& y' ~% g( k
  64.                 #region 离线消息处理- H' t+ R* D3 M
  65.                 if (MESSAGE_POOL.ContainsKey(user))& _( V) f: X% F8 Y5 k
  66.                 {, e4 `; Z4 A2 s* I' ^: [
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];+ `8 S& m3 d  e- T: m
  68.                     foreach (MessageInfo item in msgs)
    5 _* x+ k* E' w& o
  69.                     {2 S) O0 Q4 J  Y
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);  R& ~) T6 F0 @: e- G5 F: B+ u/ U
  71.                     }& T7 {6 n/ F& i9 n  d
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    ) h8 q2 f; m% v2 |
  73.                 }
    0 W9 p# n: [6 i3 n% e
  74.                 #endregion
    5 M) q& F1 `# r0 `' Y% @4 j- _
  75. 2 x4 A! w- W5 }* G
  76.                 string descUser = string.Empty;//目的用户
    ! S+ e( A! v$ W$ X' `: g
  77.                 while (true)4 k' B* ~; h$ P# p! A3 r
  78.                 {# c- l; w  r' `- P# X$ C7 I) w
  79.                     if (socket.State == WebSocketState.Open)% Q6 q, m# Y! \' c9 g9 J; C
  80.                     {
    & p9 k( i9 \+ k; X
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    7 ?" H3 j( |- \2 ^8 ^2 B
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    & s1 G1 s' s- m: m

  83. ; m0 [( o, q0 Z: M% z8 ]5 y2 A
  84.                         #region 消息处理(字符截取、消息转发)0 _4 G# \  v, m" i, a
  85.                         try0 a5 f( o1 }% g7 B% a; R& ?) ^, D
  86.                         {5 @& g; x5 ]: H. m$ b
  87.                             #region 关闭Socket处理,删除连接池$ K, z: t2 q2 o$ U
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    : {7 B; T( T0 `) r
  89.                             {
    ; m/ [  N! B7 [% c4 I  {, E
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池. j3 b- e( S$ t2 L
  91.                                 break;
    : n, ?  P& X8 _$ Y2 a2 w; L5 d  z2 F
  92.                             }1 j) w( ]+ B8 @3 z) u( d
  93.                             #endregion
    ; [# P4 r, g! f' J3 A7 e# [) T  m4 ~
  94. , @' e. n' q8 @
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息4 G& T5 J& l4 G; R
  96.                             string[] msgList = userMsg.Split('|');
    ) W+ x' r: P$ b6 t
  97.                             if (msgList.Length == 2)* S1 }- }, A" ^' k! P5 Y
  98.                             {& @4 }2 i6 V5 f
  99.                                 if (msgList[0].Trim().Length > 0)/ G9 K; J/ B5 S# B7 ]- i" `
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    % P  M; W8 O/ _+ b0 U
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));8 z3 s  `: Z2 C
  102.                             }! M6 Q2 D' Y6 [5 `: d0 Y2 Y
  103.                             else
    : U6 v* \# ?  |6 y# O( t
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    0 m0 ]! f5 z9 m) q6 n: s" p

  105. / h+ A1 ?& K* h3 Q8 a' A" |' J
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    & y* w/ y9 g2 P6 O2 P: K
  107.                             {
    4 p# J& L/ `; u. B
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端  O! N; y+ M2 h9 o. J# S
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    6 I9 n( R. h- U- X& R
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);, J: l9 t+ a) Y$ F( k: j. D0 o5 i" j
  111.                             }) b! Q8 @6 {6 r
  112.                             else6 S0 `+ e- V( e
  113.                             {5 y% Y1 u6 b0 \3 l6 i/ w
  114.                                 Task.Run(() =>
    " F; g: D. ~( m% M# c2 [" x4 U
  115.                                 {
    $ k0 ~) T9 [! ~$ z, m! c$ U  ~
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    ; _+ A+ t( l% R0 m' l' X  v' W7 E& b
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());& |( Q7 p* ^* w. _0 ?; C3 n
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    % f, w9 g% Q2 U5 B& c
  119.                                 });4 ~" O6 w4 S3 h8 c) G
  120.                             }4 c2 p: p2 ], @9 h5 J: ~
  121.                         }
    & V3 @  B2 j* D/ p. o. g" r$ h
  122.                         catch (Exception exs)
    8 @8 ?. F' B; v! `6 T* F
  123.                         {# I. p! w# V* z3 A
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    5 w3 k; ]9 `9 i1 [
  125.                         }
    2 W7 k/ M" ]2 |$ B  f* T
  126.                         #endregion  m6 w7 I# e4 n
  127.                     }  Y6 a# u/ e& P8 z
  128.                     else' f9 L4 I) ^. u* I3 n& [
  129.                     {
    4 W2 m1 {, L* a& C3 x$ |
  130.                         break;/ h$ l1 R6 }3 q/ J
  131.                     }
    / g" j0 k. k+ q7 [. a/ g/ i" m
  132.                 }//while end! `: t  U% l, b7 q0 P! i, }
  133.             }5 G( g0 k4 n) A2 |
  134.             catch (Exception ex)
    6 u$ u8 P( n1 G7 j4 f
  135.             {9 x; e) @9 ]4 Q1 E2 o! q) r
  136.                 //整体异常处理
    5 q" Z& u& \. X0 I: e1 j: l" y. b
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);" E) J4 t9 A. h1 t7 F) O: P
  138.             }
    $ X; v% U) K( p' d4 g, b/ ^
  139.         }4 Q5 G3 _( i4 G; K5 i% C
  140. 0 I' d2 p: O. s9 _8 f- @

  141. " C" m. H) |/ R' L
  142.         public bool IsReusable& s, U3 y( V" b  i/ P
  143.         {
    0 v" V0 e5 H7 j% N: A4 M( r
  144.             get2 P  U! T  s4 V
  145.             {
    ' G6 o8 N4 s' Q7 b
  146.                 return false;; L% z& p# _, R
  147.             }; G4 s* y9 _1 j) p3 U) S) @0 ^0 Z0 ]
  148.         }# P: \6 f1 S) G3 C. ?
  149.     }' g" }0 C  p, W8 }; Q  s" e0 V) m: `
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
0 t/ O/ F9 E! k
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-1-30 18:04 , Processed in 0.071302 second(s), 23 queries .

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