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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

* r7 I5 g/ a' i0 F# k* F
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;0 s  R; e7 h% r# n4 S
  2. using System.Collections.Generic;* Y' x! f% {6 M9 W/ H5 o# T
  3. using System.Linq;
    . i& N! ]* c# b' W; N
  4. using System.Net.WebSockets;
    $ }+ O8 t5 h- a% P
  5. using System.Text;2 D, X# S) J. O, ?- V
  6. using System.Threading;" f1 f6 }( D7 j* {, _" Q' j! _
  7. using System.Threading.Tasks;
    " G1 G; _. c, n4 q7 s% R" k
  8. using System.Web;
    4 S$ a; Q% k" P" k* `, j
  9. using System.Web.WebSockets;- A: c) E$ R9 D3 d3 k& x2 c
  10. + n3 [3 }( ~1 a9 [' x
  11. + H; V! v2 m- b& m+ w1 e) k
  12. namespace WebApplicationWebsocketHandler
    , |! A2 V  Z4 |" `5 ^( I9 f" R
  13. {
    0 C* T; n* M1 ~# k* g0 }  t" V
  14.     /// <summary>% G, ^) f5 G1 o6 N  i9 Q
  15.     /// 离线消息) U0 E+ Z1 b5 n* T
  16.     /// </summary>9 v9 J' x$ d% v0 O! Y3 c  |
  17.     public class MessageInfo
      \9 ?9 B/ |4 X0 `0 K) X/ p2 d
  18.     {
    ) K, O* z0 b% W# a$ ^
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)0 p/ s7 u  `8 n) D2 c& S, n
  20.         {
    + [' A( @* D, D3 o
  21.             MsgTime = _MsgTime;  o. v% `% i' S. L/ o
  22.             MsgContent = _MsgContent;) @& E1 L! v: G" j- g8 H
  23.         }7 f8 o- l) `0 p5 i& @2 Y. t
  24.         public DateTime MsgTime { get; set; }& q- W  h+ g0 p* Q( _
  25.         public ArraySegment<byte> MsgContent { get; set; }, \1 v& r1 g7 k  y( f0 K& ?
  26.     }* B) N' H1 x2 p# c  e: R
  27. - }8 g4 k. {( W! j  N3 J, Z

  28. * T  ^* c+ g5 w( S, n( s( h

  29. ! ^' _* ?0 Q5 f3 G' ^+ ~/ i! |0 m/ y! \

  30. ) T+ K0 t& {4 l3 o; U; G
  31.     /// <summary>
    9 c2 E6 S# H) V' H
  32.     /// Handler1 的摘要说明
    9 @9 k& W! K& [0 S  X" t5 \
  33.     /// </summary>
    " P7 I4 \+ e# c( ~9 `9 N$ e0 d  v
  34.     public class Handler1 : IHttpHandler" R! k% M. B1 i3 f
  35.     {% w8 W# G' l: A* X/ ^1 w! c" G  I
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池$ v* h, @( ~0 u6 x- c
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    " E3 U$ y: x7 H# u) y- Z
  38.         public void ProcessRequest(HttpContext context)( i5 b% v5 i' K6 B2 J5 `2 l
  39.         {
    ! ?1 F1 e: K: X
  40.             //context.Response.ContentType = "text/plain";; }" }2 F7 n% t; p' j" ^: ]
  41.             //context.Response.Write("Hello World");* V: K* ?: ]& L8 O
  42.             if (context.IsWebSocketRequest)
    ( c' W8 O" ]; N  ~8 n6 d
  43.             {
    . C' w0 F( W& R
  44.                 context.AcceptWebSocketRequest(ProcessChat);2 K0 f& ]2 F/ s; x/ K! Q
  45.             }
    3 {9 ?) K7 _' \( ]$ e5 R8 T$ P/ o
  46.         }
    . n4 Z' K* W, w- g: }  c4 F* g

  47. % J  |# O2 |9 g
  48.         private async Task ProcessChat(AspNetWebSocketContext context)% J4 B  R4 ]. {- ~: T; R
  49.         {/ k* B9 M4 ~+ Y( d
  50.             WebSocket socket = context.WebSocket;
    5 w, a: e" }  ~
  51.             string user = context.QueryString["user"].ToString();' [  \8 l. Z% x
  52. 4 f2 O+ E# q: L/ y
  53.             try( r0 Y3 S, q. a8 F) m1 R6 K; g3 O7 p
  54.             {
    1 w9 g+ e/ X! Y1 j( ~/ @
  55.                 #region 用户添加连接池
    " C# Y8 F  J1 s) f
  56.                 //第一次open时,添加到连接池中
    ; N' ]; {4 Y  L3 h
  57.                 if (!CONNECT_POOL.ContainsKey(user)). c4 D, B4 l! L
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    6 _: n) a  a% ^
  59.                 else
    3 h; c+ Z" I$ N$ |; L
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新5 j- c' J8 L* L
  61.                         CONNECT_POOL[user] = socket;
    5 b% t6 h' T: n0 Q8 y$ p
  62.                 #endregion
    . B$ A7 k5 s4 B( ?
  63. . S( G7 T$ ?6 E4 R& Y8 a
  64.                 #region 离线消息处理2 c, _$ d6 ~) ^& F2 x
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    ' {0 C7 h4 r7 X, u/ \
  66.                 {
    $ o; Q" I3 ?7 B4 i* X
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    + p" i- \* t4 B, `/ B
  68.                     foreach (MessageInfo item in msgs)6 u/ t# Z6 @6 p( Y! {6 M; X; B
  69.                     {8 Y# ?) e. @4 I! L7 E. W6 H
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);8 J1 H. f/ I5 u& M4 a
  71.                     }3 r$ g3 ?$ \( M4 x1 Q8 T0 ]
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息% a& B+ n* m& P$ o
  73.                 }
    . J6 }5 \+ w( ^9 Z5 l
  74.                 #endregion
    % L/ Y) t) M1 T+ e6 _
  75. ; q& X0 h# S6 v( j: n( p
  76.                 string descUser = string.Empty;//目的用户
    4 _# }: m6 m  k0 D/ z8 t4 Y
  77.                 while (true)
    $ O; |6 l. P9 M) s
  78.                 {
    & b3 m% N1 N& H3 f; p( X6 M% n
  79.                     if (socket.State == WebSocketState.Open): T' A8 h8 Q+ ]/ H
  80.                     {
    ' R8 a$ J. P1 t; n
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);5 }3 k# P& s+ y
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    , W" e* {  a) x5 r% i' z/ s. H; x

  83. " b; Z7 Q# `  t: E2 o
  84.                         #region 消息处理(字符截取、消息转发)5 e/ o5 f6 w: ]. D6 S  R
  85.                         try, ?# F0 Q" N* Q0 Z* H& w) w
  86.                         {
    / }5 e1 h  c  k! F5 M/ ]
  87.                             #region 关闭Socket处理,删除连接池
    # x$ A: s/ Z! v" V7 N
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    ) h9 L4 P, j/ l
  89.                             {
    ! z' _  v6 ~0 {9 v1 v; B
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    : N9 P6 r, E1 Y9 j
  91.                                 break;0 q: q( @. \0 i, H8 V6 q
  92.                             }; U) C7 S1 N# J7 q! f
  93.                             #endregion3 c# ^: m( h1 P; R

  94. - w( k$ a) F" G. V
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    ' F7 N. V4 N6 ?0 E$ J: G
  96.                             string[] msgList = userMsg.Split('|');5 W# f* c: F; |3 U6 K
  97.                             if (msgList.Length == 2)) ~7 J( [1 C4 @, v. K0 r
  98.                             {
    3 A2 a4 L; Q* I/ T. I
  99.                                 if (msgList[0].Trim().Length > 0)
    ! M: h# L' Z* p! _1 Y
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    9 n' ?  Y; Z* Z+ Z7 U* ^9 [0 ?# @
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));+ K3 d0 G* @/ e
  102.                             }
    ' Y/ a- d3 }: u. e
  103.                             else
    % ~0 }& b1 y/ x; j% b
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    3 d- g( U. a2 v0 D" F

  105. % O: T, G' F: Q; C
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线% y# X" S) V% D: F9 O3 X) M4 z
  107.                             {
    ! X* {' A) N1 C( X2 B. }
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端1 D  n1 |2 r7 d; S+ P" \6 S. W  G
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)5 P' C& u3 J/ ]# @
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    ( @3 D2 O' K' V& U! V; }
  111.                             }
    0 `8 ~9 i) g2 a$ _+ P
  112.                             else, U4 K! H3 f& l/ s; x8 {
  113.                             {  |/ z/ s5 S: [3 Z$ p: {" M
  114.                                 Task.Run(() =>
    / r  t- \& \6 C. V
  115.                                 {
    4 K0 j& h% k0 W, P7 B
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    6 o7 {( ]7 e4 m2 U5 r
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());5 d1 _  p* j5 u
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    ) Z2 a' e0 Q% L0 d
  119.                                 });. A6 m/ n; d0 p- Y& o$ I" \: o
  120.                             }
    5 m; c) ^0 W2 D: f3 {
  121.                         }0 A( v* d' Z5 g, i  I* s2 F
  122.                         catch (Exception exs)
    - f# g. z6 U' x, v% ]5 t8 e# t& V
  123.                         {
    4 ~' Q& I; K. J; ?3 j2 [6 f
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息. u) `  I  [  X
  125.                         }0 m9 a. c* o' U+ `
  126.                         #endregion
    9 B- f5 V( l# n
  127.                     }2 J1 N, D: g% \/ Y& q( g" d9 {. h
  128.                     else
    9 a1 w  m5 {( ^0 N9 r: g
  129.                     {* d. R  {6 V& O+ Q! J
  130.                         break;
    : j+ v( e6 Q* \, {$ H9 n) t
  131.                     }" b$ x4 a/ V" j- Z. C" N
  132.                 }//while end
    # M: [4 }/ C) s% J# ]6 B# O2 Z$ E
  133.             }; Y9 V5 v* ^; \4 t2 k" o/ G
  134.             catch (Exception ex)
    9 {0 u& o1 G, B, i4 K
  135.             {
    6 \5 j6 W; G1 r3 o4 u6 d8 t
  136.                 //整体异常处理
    : ?3 G7 u9 o; ?8 k% e$ h( t6 c
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);- P8 s- M2 Y# t
  138.             }
    # A' K" X3 c6 |) n- K) U" w- m, g, o
  139.         }
    / s, U1 H4 G$ B' f/ C+ ^: _
  140. % _4 R' W% T* Z8 p+ H
  141. ( r9 t% @( ~% O% T% i
  142.         public bool IsReusable, j3 V$ r! w9 O2 k) s
  143.         {
    * {& x' E0 g  n8 f5 j- ~, F
  144.             get
    ' [0 g5 I% \7 Y( M  @( @- O6 @2 H
  145.             {
    # s  n! j5 Z6 V3 P2 T& Q
  146.                 return false;+ u) X+ \6 ~: ^" R$ Q- y
  147.             }( w5 m! j) p. s# T$ R  W
  148.         }7 V# m0 e, d( \: ?% X: N
  149.     }
    ( J; I; S9 D! @
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
( W2 X  e- {9 u& g% C6 @- U" M
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-4-30 20:50 , Processed in 0.087946 second(s), 22 queries .

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