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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

2 x0 l$ S6 \( x1 i
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    & j- {( m0 S8 |* I- M+ v& E3 Z6 V, e
  2. using System.Collections.Generic;- z9 Y1 g. S) K5 m/ S
  3. using System.Linq;1 u2 L" m9 R5 R7 l/ V3 l0 o* [* \8 g3 P* O
  4. using System.Net.WebSockets;% _. ]9 R& m+ d  r4 p  h0 s4 x0 J
  5. using System.Text;
    3 i. C2 w" ]! X' B( J0 @3 {
  6. using System.Threading;% m- V9 H! S1 S/ f
  7. using System.Threading.Tasks;
      j! o+ D6 v+ T' D2 i* k6 E: Q
  8. using System.Web;6 t- j, a- J6 j; \" m7 K
  9. using System.Web.WebSockets;: Y2 A, H- P. c9 V7 I$ a8 k
  10. ( G5 X9 w" k/ k: {- A
  11. ( ~0 D+ ~7 l' \4 X
  12. namespace WebApplicationWebsocketHandler
    ! J% V; c" X9 o4 H/ Z6 U
  13. {
    2 i% }7 K2 |; o. T
  14.     /// <summary>' n% L/ I0 m4 x6 R) ?+ F
  15.     /// 离线消息' K! c1 g. p  G) h& Y
  16.     /// </summary>" {- w5 i4 y: s5 F
  17.     public class MessageInfo
    ' p6 [1 l; k$ U. r+ _4 z; @9 {, G' D
  18.     {; U- Z5 E# J# x1 j4 {. U
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent): _. l4 f& u% O: g* S0 B& n$ |$ I
  20.         {3 g) r2 `7 G/ Q' n3 k  J9 r8 b: B+ ^3 f
  21.             MsgTime = _MsgTime;* t4 Z. G2 \1 l# d' v
  22.             MsgContent = _MsgContent;& V% E) N+ w* M! l" j  v' Z3 G# H, J
  23.         }
    # d* _: h( d" P2 a7 I
  24.         public DateTime MsgTime { get; set; }
    3 j" t/ Y3 g- n  s0 Y+ G' I+ G+ ?
  25.         public ArraySegment<byte> MsgContent { get; set; }3 U3 |/ U/ D5 |
  26.     }
      b, f4 H& k  m

  27. ( a8 Y; g) h8 {
  28. & }: e" s4 |' L/ l0 [" \, o% o
  29. # f" H/ I9 Y" x/ d: l" B) F
  30. * Q" s0 ~% K; K- @
  31.     /// <summary>
    ! T2 z; y5 s. p. t5 ]
  32.     /// Handler1 的摘要说明- `5 D- R8 e! n) P
  33.     /// </summary>
    # {8 l' O6 F! g9 @- L  l
  34.     public class Handler1 : IHttpHandler
    ( G. T% C6 L" c" r2 o+ M( Y5 G' D
  35.     {
    : P% _+ u3 n1 x4 I" o+ I
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    ! |$ T3 b( g( P: J5 d/ |
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    & b, P& |  _1 G% ?! }! w% Q
  38.         public void ProcessRequest(HttpContext context)
    0 h, H" E' a6 I, q6 T# D  `6 R- U9 C
  39.         {: g' Y" N" k( I, G8 L( @
  40.             //context.Response.ContentType = "text/plain";
    4 h3 W/ D% r3 `) |- v. X
  41.             //context.Response.Write("Hello World");" A, [' S, X$ ~8 A
  42.             if (context.IsWebSocketRequest)5 q( ]! J, A3 m9 ?
  43.             {. [9 B2 J+ G7 r1 t. g8 M4 S
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    8 B$ G5 b8 z6 M9 y) a4 J4 @$ r- S6 Z
  45.             } ; U2 y$ v' J; O, t' _
  46.         }2 P4 R: t; V9 b& t: O) x! D

  47. 3 C6 R# D; Z" W2 x0 [: i& p% `! _& d1 ~
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    1 }7 K# D% f4 S7 {1 y
  49.         {6 P* a7 \. u  v
  50.             WebSocket socket = context.WebSocket;
    4 y# d6 v3 T7 B6 Y$ D; ~- h
  51.             string user = context.QueryString["user"].ToString();2 o& `7 |. Z+ \* b$ A8 e
  52. - P; A5 u8 w7 S: z/ x
  53.             try4 c6 @% Z) B0 [  b( Y% n
  54.             {
    ! n5 Y2 [6 q, i0 P  X" o- |6 u+ s
  55.                 #region 用户添加连接池) m3 R, Q! l, ]9 n6 S# `
  56.                 //第一次open时,添加到连接池中
    : p, i0 e) d( s% e
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    $ c/ M" ]' p4 p: Q( |8 E
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加6 e) O- z# g2 z: u( a& s% ~
  59.                 else9 `) K( s2 K9 h6 H
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    5 B% P% z5 ]% u9 y8 ?
  61.                         CONNECT_POOL[user] = socket;
    9 [3 X3 _; C9 z* b8 o  ~, Y$ l' |
  62.                 #endregion
    . Y& |7 u/ q" e8 O  T6 ?

  63. 5 M. g! z7 t5 @1 U: l8 v
  64.                 #region 离线消息处理
    # a% |" R3 ^, ]* X% B8 C+ A" Z) |6 `
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    , Z+ f- U. a9 x
  66.                 {
    & p' M' e7 }! X8 @5 L
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];6 R1 s% i& s% f
  68.                     foreach (MessageInfo item in msgs)+ m+ k. c! ?# I' U: Q$ k
  69.                     {4 }; c( C" ?& H& ~
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    ' A4 ^, X4 n0 U3 ?& _% e& h$ H4 _
  71.                     }  b( Z: a& y) C# C& ~
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息. h! X; J8 t. I! [
  73.                 }& f& }0 c$ Q1 d$ k# Q
  74.                 #endregion
    ; _* y) a5 d" r. q1 n
  75. 9 I& f" P. X( ]* x5 D- {
  76.                 string descUser = string.Empty;//目的用户! t/ @9 C, Z3 X
  77.                 while (true)
    $ k9 I$ z; S2 k: I
  78.                 {6 G. j+ C( E. Z( c* b( K- C0 S
  79.                     if (socket.State == WebSocketState.Open)* p+ Q6 j2 l" n; M) R
  80.                     {
    9 r# i3 n( ~8 V5 }
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);( \$ M' o6 q; |: j: Q; Y8 c$ y
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    6 ?6 s* f) S$ {: X0 r, \$ G
  83. " N+ F, _; |' {
  84.                         #region 消息处理(字符截取、消息转发)5 Y- x" O' E* q, m! r+ M
  85.                         try
    / i7 X  `) |: q: h7 m
  86.                         {
    * H5 ]# W3 \1 a9 Q- k
  87.                             #region 关闭Socket处理,删除连接池% F2 r, p& b0 F6 y' h  F; @" D! O' y6 _
  88.                             if (socket.State != WebSocketState.Open)//连接关闭: ]' g0 I: X: L
  89.                             {( |* O$ s/ N; }1 L  S
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    ! x1 V3 M- e( c) V
  91.                                 break;6 P' \" Z: d/ k5 k! U- E
  92.                             }% \) b6 D; z0 F6 U1 r$ u
  93.                             #endregion
    ) d/ ~7 H% q8 N

  94. 7 E- y4 U2 M, T8 r3 K4 j- |6 R  w9 z* h
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息( ~5 d, y$ K1 c' ~7 J
  96.                             string[] msgList = userMsg.Split('|');
    8 {$ s' @; w: h
  97.                             if (msgList.Length == 2)
    * \7 F6 D% x/ p
  98.                             {
    / {. t5 T% |" V7 z- ^- X1 P$ f3 h" B
  99.                                 if (msgList[0].Trim().Length > 0)3 E0 ?) ~* p7 l; g! b
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户: z; D. q( w+ x+ f
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    / h' b9 F1 H' n6 V
  102.                             }/ R. F8 q" S* o" Z; P& Y+ B( |
  103.                             else5 f8 J6 ^( j0 b
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));% i+ O! Q1 R$ u; P5 H' t$ y6 i

  105. " N* f7 d2 p4 i* a
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线' Z9 ~, g6 _2 m$ p( [+ u2 D
  107.                             {
    & i, R# T2 k, N$ D6 ~' D
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    + A' x2 H+ u  A% k
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)( Q& {6 D! b  N( ?
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);, k& N0 j0 w3 {3 i1 L2 e$ C
  111.                             }* `; Y0 W: c9 E, O; x
  112.                             else# g& h9 T" Z* k2 G
  113.                             {" j4 }: \) V/ C+ K- A  G0 L  }* i) p
  114.                                 Task.Run(() =>
    4 U+ ]  G3 o! J6 B
  115.                                 {
    9 R9 N. u) V$ q0 a
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中- Y& p$ K* z. t( T  u8 Z  A, ~
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    / y/ b1 _+ x4 Q! D
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息7 A7 r& P( M* C3 h2 I- e
  119.                                 });
    ; n' L  E0 {1 g7 m
  120.                             }: a9 R/ C4 W5 {- m4 _- H
  121.                         }
    / @7 A; p0 p# G9 v
  122.                         catch (Exception exs)
    * O  A/ q) S% ^) a
  123.                         {
    0 A9 q: A. X9 U  r3 m" _
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    5 y8 p. E& F( Z9 P$ X
  125.                         }
    0 o; Q( h* B* R! K  W, s7 c5 D
  126.                         #endregion& P8 i- X0 ]! `( x% l, {
  127.                     }3 W( F) x" ~; S) A/ w# O# ^
  128.                     else2 d& }' i3 \5 e' G) b4 `4 P5 d
  129.                     {9 W, E1 I( o! G2 ~# ~$ s" {
  130.                         break;
    ( r! s" {. d: C, ~
  131.                     }/ @- n; F* }( H% [
  132.                 }//while end
    & f+ `. ^! F- _) b
  133.             }
    * m# o! R  O7 }' n* `9 i
  134.             catch (Exception ex)6 U  O; G+ P9 e. I
  135.             {6 J. R; v; k9 U$ _( g
  136.                 //整体异常处理
    $ ^- H% @/ Z! u0 ^. f6 ^! I! s
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    % g/ Z" X3 v( V0 Z
  138.             }( s& ~! z4 o" _  g
  139.         }7 Y4 L6 j( O. [

  140. * u! X! |1 P/ i7 c2 s

  141. ( b) o8 D, `  Q8 `
  142.         public bool IsReusable
    & H: {% e+ L6 q# S" D
  143.         {
    $ O8 |+ V( G, d% `' a  Z
  144.             get, H' [$ J0 X: l) |
  145.             {; x1 S( e$ h* w! h; q5 t
  146.                 return false;
    6 G; T, O1 Q6 p0 H7 \3 B& p  q. m
  147.             }: z% x1 h+ ?, ~# R# R
  148.         }7 v8 \7 \% k8 R; W3 b
  149.     }$ w# y5 j0 i. E
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

. L3 _' u# d# T9 ~0 _! G4 n' N  W
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-8-4 08:14 , Processed in 0.054098 second(s), 23 queries .

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