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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
. y1 g9 S" b( N" S0 T3 s
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;& U3 A  ^: ]$ Z$ X# q3 J$ H
  2. using System.Collections.Generic;' ^2 k) p- U; }4 e, ]8 \! u
  3. using System.Linq;
      ~3 _$ X. J" g% R$ Y7 p
  4. using System.Net.WebSockets;
    / y6 Q2 ~+ d: z/ y
  5. using System.Text;
    1 M, l/ O: F1 w5 v1 @! e
  6. using System.Threading;7 O3 U- S+ }  r! V( x4 G
  7. using System.Threading.Tasks;2 A' L( N1 C% ~$ Y) _
  8. using System.Web;8 Q* I7 Q6 M" v+ h8 c
  9. using System.Web.WebSockets;
    ; d3 T8 K" {$ C3 V' l8 T

  10. 0 Q2 S: o5 K" }9 {' _; A

  11. ! b: @7 \, z, f) D3 j, M8 T# _
  12. namespace WebApplicationWebsocketHandler
    2 u: m: p, |+ u
  13. {
    8 _: ?& d  D8 I3 P8 h0 d3 D
  14.     /// <summary>
      J7 ^  Z% _6 F+ p& }
  15.     /// 离线消息
    7 m" M+ Z  o" Q- R
  16.     /// </summary>; H1 |1 t: ~- V0 e1 V
  17.     public class MessageInfo
    8 b5 j; j& @2 ?
  18.     {
    ) ^4 {, D" c% h  ]7 ]
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    3 k6 `( [+ c. K" F
  20.         {
    ! V: Q3 v" _, A" c
  21.             MsgTime = _MsgTime;. T  ^8 G- C, |: m2 S1 q# l+ w) N! w
  22.             MsgContent = _MsgContent;& u, S2 H) L& R! U6 U& O
  23.         }" M* m& y9 R& x0 J* @6 Y  Z9 u7 h
  24.         public DateTime MsgTime { get; set; }
    - f; r& g! Q# W, q
  25.         public ArraySegment<byte> MsgContent { get; set; }
    ! [5 V5 X4 W' ?
  26.     }0 ?: ~' m1 t  j* Z
  27. ' i6 _( _0 R2 F6 B" `; q& ~
  28. ) g2 C" m5 j4 E) z0 r* t2 ^* N) F

  29. 3 z: G7 }" F* c. q4 t4 c% }

  30. . Q% \, A5 T( L; ~1 n
  31.     /// <summary>8 }5 z# m' A/ m% K
  32.     /// Handler1 的摘要说明
    # L: K4 G" w) z
  33.     /// </summary>
    ' I% N3 ?4 \  A% x3 ~$ A; m
  34.     public class Handler1 : IHttpHandler# C$ j1 N& c! V
  35.     {( i3 p" P. v! q0 r% q5 {' a# @9 B  K
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池# a. V6 _1 d* J7 o
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    1 o# H5 ^; `, s* F0 A
  38.         public void ProcessRequest(HttpContext context)
    2 p4 u& I5 @: |# L3 b6 G0 j4 a% D
  39.         {2 D& b! E) q8 A# t8 K1 R
  40.             //context.Response.ContentType = "text/plain";: W; z% u  b& s8 Z- V
  41.             //context.Response.Write("Hello World");, k: P. _* R5 Y, l- U
  42.             if (context.IsWebSocketRequest)
    0 J1 ]- K5 |4 X* s, f  r
  43.             {9 A. E+ m0 _, ?& o
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    4 M4 m* S/ y( ~5 T& T% m# }
  45.             }
    - k& u- K/ C  ^& H" i
  46.         }
    9 J4 l+ w9 U% A1 k  l/ {) H

  47.   l! P/ H, c- `1 n7 H
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    9 g8 a& V3 Q) y* @2 U0 f5 s
  49.         {
    4 c$ [* x3 U- y$ u; R; ]
  50.             WebSocket socket = context.WebSocket;; C0 [/ \% ^& Z! T+ s5 v9 ]
  51.             string user = context.QueryString["user"].ToString();
    * c, I: l0 w' ~! @: j' `+ c1 y7 g
  52. % h8 p3 `' ^; B8 A& B
  53.             try
    9 \$ [3 B8 {& K& O4 T5 f
  54.             {
    ' M$ c7 q8 l, O% v
  55.                 #region 用户添加连接池3 o! c7 N. P1 Q/ g; A' J  _: W
  56.                 //第一次open时,添加到连接池中
    7 l- E1 P, D9 l  h! _8 f
  57.                 if (!CONNECT_POOL.ContainsKey(user))# O4 y* Z0 n" \& A
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
      g/ R8 z* ^3 h
  59.                 else7 A  v) v$ B2 j9 o( j
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新2 H& |; j) L+ a( l
  61.                         CONNECT_POOL[user] = socket;
    % }$ F8 E; P9 ?
  62.                 #endregion
    5 c, @1 D' D) E3 K/ M# G" S+ U5 b: l
  63. 0 M4 j8 f4 n  y) m$ [* F% f9 U- h. h
  64.                 #region 离线消息处理
    ' e, p7 f4 n4 _$ I2 q* t
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    & \' f2 \/ v/ ]/ L. n
  66.                 {. {- M) B+ \3 j+ y$ }
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];# W9 v0 x# Y/ L- t4 Q9 K8 L
  68.                     foreach (MessageInfo item in msgs)
    / p: P: r0 c9 T4 v6 j
  69.                     {
    . s1 g5 g3 n2 H$ R
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    ) G+ g" m4 ~$ r' k
  71.                     }' Q" Y0 C7 |; n' O; ?/ ]
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息4 w6 Y/ ^5 r0 R7 q; c& W
  73.                 }
    2 D" Q* o% G7 W( R% V) y* Q
  74.                 #endregion
    , r5 ?( `9 P- ?. Q. o: e
  75. . B* E6 h- P% }* e, ?
  76.                 string descUser = string.Empty;//目的用户
    - i8 l5 T, j! g
  77.                 while (true)
    & A; |7 D5 z+ g0 l( w0 ?
  78.                 {
    ; X6 y2 U& y% {# Q9 ^& V
  79.                     if (socket.State == WebSocketState.Open)6 U% d6 I4 T3 s- B
  80.                     {, o7 V6 y7 h- c  L9 |) {
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    2 m2 X$ B  q, [6 w) g, b1 C
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    0 F7 _  I7 I; V" J3 S- g
  83. ( Z. I. ]$ [1 h2 L- y: |" }
  84.                         #region 消息处理(字符截取、消息转发)+ W- \& i8 x, z- x4 x- Y8 Z! b, S
  85.                         try+ o/ G3 j$ d9 J; y! g/ t
  86.                         {& y8 \; Y/ m' N. b; b4 h+ z
  87.                             #region 关闭Socket处理,删除连接池1 f4 D  U7 u6 h8 e9 T
  88.                             if (socket.State != WebSocketState.Open)//连接关闭5 V7 q! F+ n% G" @1 @7 p6 u
  89.                             {. c9 t: Z; i) G8 B7 H
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池) u4 Y0 `3 q$ i' P0 u$ M, R4 ?
  91.                                 break;& G  \0 T! D  I6 s( r7 M$ q2 `( n
  92.                             }0 u5 ]1 [. |$ z4 j
  93.                             #endregion
    ! [: L7 @3 S$ j% L+ @9 H' \! I- D6 Q6 i

  94. + b7 `2 S, B) O% e; x
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    4 s- p4 L+ j& g+ H0 u" Y- g
  96.                             string[] msgList = userMsg.Split('|');
    : V% v& o" R. k9 P4 x& `$ ?2 P$ N
  97.                             if (msgList.Length == 2)
    0 L9 K( r4 d: j+ Q
  98.                             {
    2 E% p# A! o* c7 p' X
  99.                                 if (msgList[0].Trim().Length > 0)
    9 x  D' K( w( L( \" X) @
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户" D9 N4 A# C- o3 ?0 E) `
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    1 b2 J1 p% m# d- k. K% L+ ?( J2 {
  102.                             }
    6 t; H" F3 }0 Q2 T
  103.                             else# B) w4 q! w1 Y/ r9 m5 {$ s+ s/ T
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    # `: E! H! u# J3 K* f( f( F$ }

  105. . v: ?, \( V$ f+ v) C# e/ o
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线' h# T$ h. ~5 C$ e9 S# f8 a
  107.                             {4 O9 r) W& q4 K0 h
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    3 `5 Q! y4 B* b: l+ M7 c2 s) I& G0 N
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    - J/ e8 K& e- t
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    / \" j  C" ?- S0 a$ U9 d
  111.                             }) _8 [3 J) m' J" M0 Q
  112.                             else
    * z7 U4 @& m  a. N- Z1 P, T
  113.                             {9 |8 Y( ]; \2 f6 S
  114.                                 Task.Run(() =>
    & `9 t+ u0 |6 {# ?: S2 d
  115.                                 {; t3 ?. y2 j6 I
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    , n; H) Q- r7 v0 c0 U' J6 s
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());& ?9 y+ q3 _9 O9 L* v. {% G
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    , }8 f3 `! R# d( g/ r# k
  119.                                 });
    ; a4 \/ e/ h2 ]" q0 {  E. M
  120.                             }. G8 A8 y1 i& O* g
  121.                         }
    : e0 e/ Y4 `0 s" V: Q- I
  122.                         catch (Exception exs)
    / j4 T. A% @0 ?% J  E
  123.                         {6 |4 P6 ~3 T4 j: o- V1 |
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息2 |' W* C& m- \% k4 ?
  125.                         }+ Y/ p+ q" F& p( F( k
  126.                         #endregion1 I- S* e+ b5 Z" t
  127.                     }
    ) B- G. I* \. ]' b) f2 f9 E+ p
  128.                     else
    3 ?/ Y) E# L' q9 u
  129.                     {
    & d! p5 V8 P' F# N( ^
  130.                         break;
    & b4 H& V; ^2 C  a9 ~0 n
  131.                     }
    . u: j& f' n; P9 I) l0 N. V/ D
  132.                 }//while end
    # U% z" M5 ?1 K4 l3 x
  133.             }9 L& ^; @! y+ X0 v
  134.             catch (Exception ex)
    ; [5 F  X! f9 G& h
  135.             {
    - C! ]% g/ W% J6 r3 V2 a( c" M
  136.                 //整体异常处理4 U% h" V1 R5 K# S* V' ~
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);/ ^0 }! G* g* R5 G
  138.             }
    0 @  `& \" J. _7 X
  139.         }
    % I3 ?5 [1 e  {) j. X& X
  140. ) x6 o& T  a0 M5 k
  141. + W' G8 e! `( s- W# q! z2 l
  142.         public bool IsReusable6 S. R; F0 n, k
  143.         {
    3 {5 ]+ X- K( E8 p+ q
  144.             get) f% A  o! ~7 [' z+ Y
  145.             {
    " s) F0 D6 q6 a& }3 R7 d( }
  146.                 return false;
    * D# i+ `0 T+ P7 A
  147.             }
    # T/ a1 V3 p) d! D
  148.         }
    " z0 d( a3 s8 V) K* N" d+ m
  149.     }$ F2 P  v: j5 C- R4 d! t: f
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

" x0 U- Q* W4 N( j
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-12-22 20:11 , Processed in 0.112075 second(s), 25 queries .

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